Markus Michalski FAQ

LeaveFlow: Installation

Installing LeaveFlow with Docker Compose: requirements, migrations, setup wizard, environment variables, HTTPS, update and development environment.

Deutsche Version

Back to overview

LeaveFlow: Installation

Requirements

You need Docker with the Compose plugin (docker compose) and Git. You do not have to install PHP or MariaDB yourself, the Compose stack provides both. The remaining requirements are on the overview page.

Installation

  1. Clone the repository:

    git clone https://github.com/markus-michalski/leaveflow.git
    cd leaveflow
    
  2. Start the containers (builds the image and starts the app, database, Mailpit and OpenLDAP):

    docker compose up -d --build
    

    On the first start the container installs the Composer dependencies itself and builds the Tailwind stylesheet. This takes a moment, follow the progress with docker compose logs -f app.

  3. Run the database migrations:

    docker compose exec -u app app php bin/console doctrine:migrations:migrate --no-interaction
    
  4. Open the application in the browser: http://localhost:8080. As long as no company exists, LeaveFlow redirects every page to the setup wizard at /setup.

The stack is a development stack: compose.yaml builds the Docker target dev and sets APP_ENV: dev. The host ports come from compose.override.yaml (8080:80, 8443:443, plus 3306, 1025 and 8025 for the database and Mailpit). The Dockerfile also contains a prod target, but the repository does not ship a ready-made production Compose file.

Setup wizard

The wizard at /setup first checks the system requirements and then creates the company and the first admin.

Check What is checked
PHP version PHP 8.4.0 or newer
PHP extensions pdo_mysql, intl, gd, mbstring, json, curl, ctype, fileinfo
Database connection Connection to the database
Database migrations All migrations are applied
var directory Directory var/ is writable
public/uploads directory Directory public/uploads/ is writable

While any check is red, the form cannot be submitted. The form asks for the company name, the admin email and an admin password of at least 12 characters. The wizard creates only the company and the admin account and runs once. Afterwards it shows the completion page at /setup/done with a list of next steps and the button Go to sign in, which leads to the sign-in page.

The wizard creates no absence types, locations, departments or employees. You do that afterwards in the admin menu, the order is described in the admin guide.

Configuration through environment variables

Symfony reads .env, .env.local and .env.dev. Environment variables that the container receives directly take precedence over all of these files.

compose.yaml hard-sets DATABASE_URL (with the password !ChangeMe!) and MAILER_DSN (smtp://mailer:1025) as container environment variables. Values from .env.local therefore have no effect for these two variables. To change them, edit compose.yaml, and change the database password in all three places (MARIADB_PASSWORD, MARIADB_ROOT_PASSWORD and DATABASE_URL).

Variable Meaning
APP_ENV Environment; compose.yaml sets dev
APP_SECRET Secret for CSRF tokens and signatures, unique per installation. Empty in .env, .env.dev ships a value for development
DATABASE_URL Database connection; the host in the stack is database
MAILER_DSN Mail transport; smtp://mailer:1025 (Mailpit) in the stack
MESSENGER_TRANSPORT_DSN Queue for asynchronous messages; default doctrine://default?auto_setup=0
DEFAULT_URI Base URL for links generated without a browser request (console commands, cron jobs, queued mails); default http://localhost:8080
SERVER_NAME Address the built-in web server listens on; default :80
APP_LDAP_ENCRYPTION_KEY 32-byte key (Base64) used to encrypt stored credentials for LDAP and Slack
GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET OAuth credentials for Google sign-in
ENTRA_CLIENT_ID, ENTRA_CLIENT_SECRET OAuth credentials for Microsoft sign-in
ENTRA_TENANT_ID Tenant for Microsoft sign-in; default common

There is no APP_URL variable. The base URL for links outside browser requests is set by DEFAULT_URI.

Docker Compose evaluates SERVER_NAME at start from the shell environment or from the .env in the project directory, not from .env.local. Generate the value for APP_LDAP_ENCRYPTION_KEY with:

php -r "echo base64_encode(random_bytes(SODIUM_CRYPTO_SECRETBOX_KEYBYTES)) . PHP_EOL;"

Without this key, the Slack token, the Slack signing secret and the LDAP bind password cannot be saved. If you change the key later, values that were already stored can no longer be decrypted.

HTTPS and domain

The PHP configuration sets session cookies with session.cookie_secure = 1. Run the instance behind HTTPS outside localhost and set DEFAULT_URI to the public address. The built-in web server (Caddy in FrankenPHP) serves the address given in SERVER_NAME.

Update

git pull
docker compose up -d --build
make install
docker compose exec -u app app php bin/console doctrine:migrations:migrate --no-interaction

Once a company exists, the setup wizard no longer shows pending migrations. Apply them after every update.

Development environment

Command Effect
make up / make down Start and stop the containers
make test PHPUnit test suite
make stan PHPStan
make fixtures Empty the database and load demo data

make fixtures empties the database completely before loading the demo data. Never run it against an instance with real data.

After make fixtures there is a demo company with locations, departments, employees, seven absence types and three test accounts.

Email Password Role
admin@leaveflow.test leaveflow-dev Administrator
manager@leaveflow.test leaveflow-dev Manager
employee@leaveflow.test leaveflow-dev Employee

Mailpit, the email catcher of the stack, is available at http://localhost:8025.