This is a working example of automate hosting Mautic 5 instance(s) on Virtual Private Server (VPS) on digitalocean.com
Hosting a web app is not an easy job. You need the technical knowledge and the time to maintain it. This repositry will help but it still requires both. Especially over time.
The easiest option is to start your 2 week trial today: https://m.mautic.org/mautic-start-your-trial
Or if you like more choices consider the official Mautic partners if you just want to use Mautic without any problems and get all the services to make your business succesful.
By using both these options you will get the bet service possible and support the Mautic project.
Do you still want to get your hands dirty? That's OK too.
This is a bit different from your normal "execute a bunch of commands" tutorials. This is automated, maintainable deploy process that will keep detailed history of who changed when and why.
It allows you to:
- Install Mautic within 10 minutes.
- Upgrade Mautic with 1 line change.
- Downgrade with commit revert.
- Install themes and plugins via Composer.
- Anyone from your team can do this. Avoid the Bus Factor. GitHub allows you to set rules that someone needs to approve all changes before they are applied.
- Project management with task boards in place.
- Security scans.
The infrastructure that this repository creates lets you start small and scale vertically by increasing DigitalOcean resources and also horizontally by creating more workers to send emails faster.
The scripts are there and ready. You need to provide keys and values so it can do all the magic.
- Github to host the configuration and run the deployment (free)
- DigitalOcean to run the VPS where Mautic will run (from $6/month)
- A (sub)domain. This is technically optional, but users won't click on links with just IP addresses.
In order to deploy Mautic, you need a few "secrets" and "variables" so it can perform all the tasks. You cannot access the value it is saved.
Github Actions is the tool that will take the code from this repository and executes it. That is the deployment process that will create the VPS, configures it and install Mautic with Docker Compose inside.
The secrets are values you don't want anyone else to see.
SSH_PRIVATE_KEY
is used to access the VPS via SSH by Github Actions, the deployment process. You can use the one you already have in~/.ssh
folder or generate a new one. Follow the official documentation to generate it and add it to the DigitalOcean configuration.- Once you have stored the SSH key to the DigitalOcean configuration, copy the Fingerprint for
DIGITALOCEAN_SSH_FINGERPRINT
at https://cloud.digitalocean.com/account/security - Create
DIGITALOCEAN_ACCESS_TOKEN
at https://cloud.digitalocean.com/account/api/tokens MAUTIC_PASSWORD
is an admin password to log in to the freshly installed Mautic. Store it to your password manager.
This is how the secrets section should look like:
The variables are values that is OK to be visible. You can edit the vaule after it is saved.
EMAIL_ADDRESS
will be used to create a Mautic admin user and you'll use it to log in. It is also used to build the SSL certificates.DOMAIN
is the domain that will be used to access your Mautic. Do not add it at first. Add it only after you know the VPS IP address and after you've pointed the DNS record to that IP address. If the DOMAIN is unknown, you can still access your new Mautic via the IP address.
This repository is a set of configurations and scripts that run automatically on every change and create a Digital Ocean Droplet (VPS), configure it, install a clean Mautic there and everything necessary including HTTPS.
The deployment process will create a VPS (a DigitalOcean droplet) for you with the lowest possible configuration which at this time costs $6/month. It has 1GB of memory and @% GB disk. It will create itself in the New York region. You can modify all these values here. You can always upgrade the memory and disk size. You cannot change the region.
Another option is to create the VPS with the name of mautic-vps
via the DigitalOcean's user interface where you'll be able to see all the available options. Once you run this deployment process it will use the VPS you've created if the name will match.
Nginx is a server like Apache. This server is installed directly on the VPS and the only reason is to handle SSL. I other words, to handle the certificates necessary for HTTPS. The mautic_web
container actually have its own server to handle HTTP requests. In this case it is Apache.
Docker is a program that can manage lightweight containers. It serves the same role as virtual machines. The difference is that containers are lighter in size and so creating them takes less time and they do not take that much space.
A container is a list or a recipe of commands that needs to be executed to build whatever you want the container to do. In this case we take this Dockerfile as a base and define our own Dockerfile sprinkle a few more commands on top of it so we could install themes and plugins.
Docker Compose enables simplified networking between the containers and 1 config file where all that interconnection is described.
The docker-compose.yml in this repository was copied from https://github.com/mautic/docker-mautic/tree/mautic5/examples/basic
There are 4 containers created with the deployment process by default.
This container is the only public container. Meaning it's the only container accessible with HTTP requests. It's the one that we interact with via a browser.
This container's whole purpose is to run cron commands. The crontab is created by this script and modifiable on the VPS as it's a shared volume. However, to continue the philosophy of this repository, it should be created and commited to this repository instead. See the Todo section bellow.
Mautic 5 started using workers for sending emails. This container is a worker that is waiting for the email jobs and executing the email send. If you want to speed up the email send speed, you can configure the replicas
configuration and the deployment process will take care of it.
db
is a container running MySql. All other containers are using this one to store and read data. The data are stored as a volume so they are not lost when this container is deleted.
Volumes are basically files and directories that are shared between a container and its host computer. Containers are stateless by default so when a container is deleted, it deletes all its files as well. If there are some files we want to keep we need to store them to the host computer. Hence that's why we have volumes in our setup. For example for files, images that you upload to Mautic. But also for the database.
One of the goals of this deployment is to have a trace of everything related to the Mautic instance configuration. Installing a plugin or a theme can break your Mautic so it's good to have a way to roll back if it happens. And to have a trace of who installed what, when and why is also great to have. Git gives us all that.
In the Dockerfile there is an example of how to install a package. In this case it is a chimpino/theme-air
theme. If you need to install anyting else, you'll just add a new line with the package you need and commit this one line change.
Cron job configuration is usually a big pain to setup for newcomers. In this case you can manage them in this repository in the cron/mautic file. Make a change, commit and it will deploy to the server automatically. Most of the cron jobs are prepared there anyway so you may not need to make any change.
SSL certificate management is also a pain to manage. In this case you just point the domain DNS A record to the VPS IP address, configure the DOMAIN variable in the Github repository Github Actions and re-run the latest job. Everything else is automated.
Digitalocean provides nice resource monitoring out of the box. Here is a screenshot how the resource usage looks after fresh installation.
If something is acting up you can see what resources each container is using with command:
docker compose stats
The output looks like this:
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
da1d14c8495b basic-mautic_cron-1 0.01% 25.7MiB / 957.4MiB 2.68% 800kB / 516kB 679MB / 10.8MB 4
5eb3bc650664 basic-mautic_worker-1 0.26% 80.15MiB / 957.4MiB 8.37% 17.5MB / 15.9MB 154MB / 320MB 9
f8089c6149df basic-mautic_web-1 0.01% 159.4MiB / 957.4MiB 16.65% 2.65MB / 16.4MB 831MB / 56.2MB 13
5d58d082d20c basic-db-1 1.29% 95.07MiB / 957.4MiB 9.93% 17.9MB / 20.1MB 824MB / 1.04GB 49
You may need to execute some command in the VPS or one of the nodes from time to time. Or debug what's happening like with the monitoring above. Here's a list of useful commands.
For all docker compose
commands navigate to the folder where this deployment script is pushing the docker-compose.yml
file. From this folder you can use the docker compose
commands.
cd /var/www/
You can controll everything from the browser. DigitalOcean has this nice feature that opens a terminal directly from the administration. All you need is a browser. Follow this screenshot:
docker compose ps
Example output:
root@mautic-vps:/var/www# docker compose ps
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
basic-db-1 mysql:8.0 "docker-entrypoint.s…" db 40 minutes ago Up 40 minutes (healthy) 3306/tcp, 33060/tcp
basic-mautic_cron-1 basic-mautic_cron "/entrypoint.sh apac…" mautic_cron 40 minutes ago Up 39 minutes 80/tcp
basic-mautic_web-1 basic-mautic_web "/entrypoint.sh apac…" mautic_web 40 minutes ago Up 40 minutes (healthy) 0.0.0.0:8001->80/tcp, :::8001->80/tcp
basic-mautic_worker-1 basic-mautic_worker "/entrypoint.sh apac…" mautic_worker 40 minutes ago Up 27 minutes 80/tcp
If there is a problem with the deployment, you can see it in the logs that are being downloaded and attached to each Github Action job as an artifact. So you can see how the deployment went without logging into the server. Just go to the summary of the job you are interested in and download the setup-dc-log
artifact for inspection.
Perhaps you want to see how the mautic_cron
container is working. Or debug why some command is not working perhaps. In that case execute
docker compose logs mautic_cron
You can do the same for any of the containers that you get from the docker compose ps
command above.
The best way is to log inside the container with a command like
docker compose exec -it -u www-data mautic_cron bash
Notice that the user, host and folder changed in your next line in the terminal. It means you are inside the container. Here is how the output looks like:
Notice you are in the docroot
directory. That's the directory where the publicly accessible files are. If you want to run some bin/console
command for example, you have to go one directory up with cd ..
.
Example:
root@mautic-vps:/var/www# docker compose exec -it -u www-data mautic_cron bash
www-data@b465afe49214:~/html/docroot$ cd ..
www-data@b465afe49214:~/html$ php bin/console cache:clear
// Clearing the cache for the prod environment with debug false
[OK] Cache for the "prod" environment (debug=false) was successfully cleared.
www-data@b465afe49214:~/html$ exit
exit
root@mautic-vps:/var/www#
This setup will allow you to start small, monitor the resources and if some CPU, RAM, Disk or Transfer will start hitting a limit then you can scale horizontically. If the emails are sending too slow, you can scale vertically.
You can resize your VPS any time and add resources as you see fit. Example:
This setup currently allows to vertically scale the worker containers. You can increase the replicas
and speed up the email sending.
Future glance: In Mautic 5 the workers are "just" sending emails, but the cron jobs should be slowly moved to workers as well. This deployment setup can also add a load ballancer and in that case we will be able to scale the web containers. Also a database read only replica can be added if the SQL requests are the bottleneck.
This repository wouldn't be possible without the great work that the Mautic community and especially @mollux did at https://github.com/mautic/docker-mautic
The links to Digital Ocean in this readme are tracked by a referal program. If you are new to Digital Ocean, you'll get $200 in credit and I get $25 credit. You can use access the DigitalOcean website any other way to avoid this referal.
- Run
docker compose build
only if necessary to save time. For example if the Dockerfile changes. - Test the build before trying to deploy and fail the CI if the build fails.
- Related to the point above, shall send the built image to some repository like Dockehub? Or GitHub and Digital ocean have their own repositories. Which one? All are limitted to 1 image, all require additional keys which will complicate the setup. But we'd avoid to build the image twice.
- Adding some service for logging and monitoring of the containers.
- Use Redis for caching, sessions and queuing.
- Make it possible to install multiple Mautic instances to the same VPS.
- Load ballancer.
- MySql replica.
- Download the setup-dc.log from the droplet to GH Action files for easier inspection.
- Make the crontab configurable in this repository.