Empowering Self-Hosting: A Journey from PaaS to Coolify for Symfony Projects


Some Context...

Since the recent dramas with Netlify and other PaaS (Product as a Service) on Twitter, regarding excessively high billing, I decided to take back control of my projects (even though I wouldn't have had billing issues) and migrate them to Coolify.

This also allowed me to host my PHP/Symfony projects without having to rely on a compatible PaaS (Scalingo, Scaleway, Platform.sh, etc.) which were too expensive for what I wanted to do.

Don't get me wrong, they're all very good (especially Platform.sh with Symfony / Symfony CLI integration), but I don't want to spend money on external services for very low traffic projects, and especially since I have my own server at home!

What is Coolify?

Coolify is an open-source self-hosted alternative to Heroku, Netlify, Vercel, etc.

Coolify allows easy deployment of projects through a good web interface, Docker containers, custom domain names and free SSL certificates, auto-deployment via webhooks, and more...

No installation tutorial, let's get straight to the point :)

Symfony Application

Kévin Dunglas, the author of FrankenPHP, a super modern and performant PHP application server, has provided a Symfony project template that works with FrankenPHP.

I migrated my PHP/Symfony projects to use this template (hugo.alliau.me, OpenGraph Image Generator, etc.), but only for production; for now, I prefer the ease of use of Symfony CLI for development.

Configuration in Coolify

After creating the project on Coolify (for example, via a GitHub repository), you'll need to configure it as follows:

  • Domains for Php: This is the URL that will be configured in Traefik to redirect the HTTP request to the correct container.
  • Docker Compose Location: Make sure to specify the Docker Compose configuration file for production, in our case compose.prod.yaml.

If everything is okay, the Docker Compose configuration used by Coolify (Docker Compose Content) should refresh correctly. Coolify UI, project configuration

Optionally, probably due to the architecture of my server (on my NAS, I have Caddy acting as a proxy to a virtual machine where Coolify and my projects are located), I had to disable the Forcs Https option to avoid infinite redirection issues, but maybe I don't need it anymore today: Coolify UI, project advanced configuration

Then you need to configure the environment variables, firstly those defined in our compose.prod.yaml which are mandatory, and optionally those from your Symfony application's .env:

  • APP_SECRET: Used for certain critical parts of the code, it is imperative to have a different value between production and that of .env.
  • SERVER_NAME: Here I configured :80, because in my case I don't want FrankenPHP/Caddy to handle host management and SSL certificate generation, everything is done upstream in the Caddy server acting as a proxy.

Coolify UI, project environment variables

tip

Since the symfony-docker template is well made, the composer dump-env prod command is run on each container build. This avoids parsing .env.* files for each request, thus gaining in performance.

Deployment

It's now time to launch the first deployment of the Symfony app:

  • either do it manually, via the dedicated button on the interface, which is the simplest at the moment
  • or via webhooks, very convenient for automatically triggering a deployment after pushing a commit to main

If all goes well, something similar should be displayed, and the application should be accessible: Coolify UI, project deployment