Adding a New Application to PLift¶
This guide explains how to add your own application/repository under an existing framework in PLift.
Overview¶
When adding a new app, PLift will:
1. Generate a Dockerfile for your app
2. Create environment configuration files (.env, application.properties, etc.)
3. Set up database connections and migrations
4. Configure monitoring (Prometheus, OpenTelemetry, logging)
5. Add routing to HAProxy
6. Generate SSL certificates
Prerequisites¶
- Your application code in the
apps/directory or a Git repository - PLift base stack running (
plift start-base) - Understanding of your app's requirements (database, ports, dependencies)
Step-by-Step Guide¶
Step 1: Prepare Your Application¶
Option A: Local Application Directory¶
Place your application in the apps/ directory:
# Example: Copy your Laravel app
cp -r /path/to/my-laravel-app apps/my_laravel_app
# Or clone from Git
git clone https://github.com/yourusername/my-app.git apps/my_app
Option B: Use Git Repository (Recommended)¶
PLift can clone your repository automatically. Just provide the Git URL in the configuration.
Step 2: Edit Application Configuration¶
Edit configs/apps/init.sls and add your application under the appropriate framework section.
Example: Adding a Laravel Application¶
{% set local_domain = salt['environ.get']('LOCAL_DOMAIN', 'plift.local') %}
plift:
apps:
laravel:
# Existing example app
example_laravel:
# ... existing config ...
# Your new Laravel app
my_laravel_app:
# Load balancer URL (required for HAProxy routing)
lb_url: 'my-app.{{ local_domain }}'
# Base Docker image
base_image: php:8.2-cli
# System dependencies to install
system_dependencies:
- unzip
- git
- curl
- zip
# PHP extensions (Laravel-specific)
php_extensions:
- pdo
- pdo_mysql
- mbstring
- xml
- curl
- zip
# Monitoring configuration
monitoring:
prometheus:
enabled: true
port: 8000
path: /metrics
apm:
enabled: true
type: opentelemetry
tempo_endpoint: http://tempo:4318
protocol: http/protobuf
logging:
level: info
format: json
destination: stdout
# Docker container configuration
docker:
name: my_laravel_app
hostname: my_laravel_app
exposed_port: 8000
port_bindings:
- "8000:8000" # Host:Container port mapping
volumes:
# Mount your app directory
- "../../apps/my_laravel_app:/var/www/html"
working_dir: /var/www/html
# Custom startup command (optional)
command:
- sh
- -c
- |
if [ ! -f /usr/local/bin/composer ]; then
curl -sS https://getcomposer.org/installer | php
mv composer.phar /usr/local/bin/composer
chmod +x /usr/local/bin/composer
fi
cd /var/www/html
composer install --no-dev --no-interaction
php artisan migrate --force || true
php artisan serve --host=0.0.0.0 --port=8000
# Application-specific configuration
app_config:
db_name: my_laravel_app
db_user: my_laravel_app
db_password: my_laravel_app_pass
db_host: mysql
db_port: 3306
# Add any other environment variables your app needs
APP_NAME: "My Laravel App"
APP_ENV: production
APP_DEBUG: "false"
Example: Adding a Django Application¶
plift:
apps:
django:
my_django_app:
lb_url: 'my-django.{{ local_domain }}'
# Monitoring
monitoring:
prometheus:
enabled: true
port: 8000
path: /metrics
apm:
enabled: true
type: opentelemetry
tempo_endpoint: http://tempo:4317
logging:
level: info
format: json
destination: stdout
docker:
name: my_django_app
hostname: my_django_app
exposed_port: 8000
port_bindings:
- "8001:8000" # Use different host port
volumes:
- "../../apps/my_django_app:/app"
env_vars:
ALLOWED_HOSTS: "my-django.{{ local_domain }},localhost,127.0.0.1"
PYTHONUNBUFFERED: "1"
app_config:
db_name: my_django_app
db_user: my_django_app
db_password: my_django_app_pass
db_host: postgresql
db_port: 5432
SECRET_KEY: "your-secret-key-here"
Example: Adding a Node.js Application¶
plift:
apps:
nodejs:
my_nodejs_app:
lb_url: 'my-nodejs.{{ local_domain }}'
monitoring:
prometheus:
enabled: true
port: 3000
path: /metrics
apm:
enabled: true
type: opentelemetry
tempo_endpoint: http://tempo:4317
logging:
level: info
format: json
destination: stdout
docker:
name: my_nodejs_app
hostname: my_nodejs_app
exposed_port: 3000
port_bindings:
- "3002:3000"
volumes:
- "../../apps/my_nodejs_app:/app"
- "/app/node_modules" # Anonymous volume for node_modules
env_vars:
NODE_ENV: production
NODE_OPTIONS: "--require ./tracing.js" # For OpenTelemetry
app_config:
db_name: my_nodejs_app
db_user: my_nodejs_app
db_password: my_nodejs_app_pass
db_host: postgresql
db_port: 5432
Example: Adding a Java/Spring Boot Application¶
plift:
apps:
java:
my_java_app:
lb_url: 'my-java.{{ local_domain }}'
monitoring:
prometheus:
enabled: true
port: 8080
path: /actuator/prometheus
apm:
enabled: true
type: opentelemetry
tempo_endpoint: http://tempo:4317
logging:
level: info
format: json
destination: stdout
docker:
name: my_java_app
hostname: my_java_app
exposed_port: 8080
port_bindings:
- "8082:8080"
# For Java apps, typically build JAR into image
# volumes:
# - "../../apps/my_java_app:/app"
command:
- sh
- -c
- |
if [ ! -f /tmp/opentelemetry-javaagent.jar ]; then
curl -sSL -o /tmp/opentelemetry-javaagent.jar \
https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/download/v1.32.0/opentelemetry-javaagent.jar
fi
java -javaagent:/tmp/opentelemetry-javaagent.jar \
-jar /app/app.jar
app_config:
db_name: my_java_app
db_user: my_java_app
db_password: my_java_app_pass
db_host: postgresql
db_port: 5432
SPRING_PROFILES_ACTIVE: production
Step 3: Using Git Repository (Optional)¶
If your app is in a Git repository, you can configure PLift to clone it automatically:
my_laravel_app:
git_repo: https://github.com/yourusername/my-app.git
git_branch: main # Optional, defaults to master/main
# ... rest of config ...
PLift will clone the repository to /apps/my_laravel_app during config generation.
Step 4: Generate Configurations¶
Generate the application-specific configurations:
# Generate app configs (Dockerfiles, .env files, etc.)
plift generate c=apps
# Generate HAProxy routing
plift generate c=default
# Generate database migrations
# (This will be done automatically, but you can regenerate)
Step 5: Set Up Database (If Needed)¶
If your app uses a database, PLift will automatically: - Create the database - Create the database user - Set up permissions
The migration will run automatically when you execute:
Or you can manually configure database users in:
- configs/databases/mysql/init.sls for MySQL
- configs/databases/postgresql/init.sls for PostgreSQL
Step 6: Build and Start Your Application¶
# Build the application container
plift build-apps a=my_laravel_app
# Start the application
plift start-apps a=my_laravel_app
# Or start all apps
plift start-apps
Step 7: Verify Your Application¶
-
Check container status:
-
View application logs:
-
Access your application:
- Via HAProxy:
https://my-app.plift.local -
Direct port:
http://localhost:8000(if port binding is configured) -
Check monitoring:
- Prometheus:
http://localhost:9090(search for your app metrics) - Grafana:
http://localhost:3000(check dashboards)
Configuration Reference¶
Required Fields¶
lb_url: URL for HAProxy routing (e.g.,'my-app.plift.local')docker.name: Container name (must be unique)docker.exposed_port: Port your app listens on inside containerdocker.port_bindings: Host:Container port mappingapp_config: Application configuration (database, etc.)
Optional Fields¶
base_image: Docker base image (defaults per framework)system_dependencies: System packages to installphp_extensions: PHP extensions (Laravel/Symfony)python_packages: Python packages (Django)npm_packages: NPM packages (Node.js)maven_dependencies: Maven dependencies (Java)monitoring: Monitoring configurationdocker.volumes: Volume mountsdocker.env_vars: Environment variablesdocker.command: Custom startup commandgit_repo: Git repository URL
Monitoring Configuration¶
All monitoring is optional but recommended:
monitoring:
prometheus:
enabled: true
port: 8000
path: /metrics
apm:
enabled: true
type: opentelemetry
tempo_endpoint: http://tempo:4318 # or :4317 for gRPC
protocol: http/protobuf # or grpc
logging:
level: info
format: json
destination: stdout
Common Scenarios¶
Scenario 1: App with Custom Dependencies¶
my_laravel_app:
system_dependencies:
- imagemagick
- libpng-dev
php_extensions:
- gd
- imagick
# ... rest of config
Scenario 2: App with Multiple Databases¶
my_app:
app_config:
# Primary database
db_name: my_app
db_user: my_app
db_password: my_app_pass
db_host: postgresql
# Secondary database (add as env vars)
REDIS_HOST: redis
REDIS_PORT: 6379
CACHE_DRIVER: redis
Scenario 3: App with Custom Build Process¶
Scenario 4: App with Health Checks¶
Add health check endpoint and configure in your app code. PLift will automatically discover it via Prometheus.
Troubleshooting¶
Application Won't Start¶
-
Check logs:
-
Verify configuration:
-
Check port conflicts:
Database Connection Issues¶
-
Ensure database is running:
-
Run migrations:
-
Check database credentials in
configs/apps/init.sls
HAProxy Not Routing¶
-
Regenerate HAProxy config:
-
Restart HAProxy:
-
Check
lb_urlmatches domain: - Should be:
my-app.plift.local - Not:
my_app.plift.local(underscores not valid in DNS)
Monitoring Not Working¶
- Verify monitoring config in app config
- Check Prometheus targets:
http://localhost:9090/targets - Verify metrics endpoint is accessible from Prometheus
- Check OpenTelemetry endpoint if using APM
Best Practices¶
- Use Git repositories for version control
- Set unique port bindings to avoid conflicts
- Enable monitoring for all production-like apps
- Use environment variables for sensitive data
- Test locally before committing configs
- Document custom commands in your app's README
- Use health check endpoints for better monitoring
Next Steps¶
After adding your app:
-
Generate traffic to test monitoring:
-
Check Grafana dashboards for your app metrics
-
Set up database users if you need custom permissions
-
Configure additional services (Redis, RabbitMQ, etc.) if needed
Example: Complete Workflow¶
# 1. Add your app config to configs/apps/init.sls
# (Edit the file as shown above)
# 2. Generate all configurations
plift generate-all
# 3. Build your app container
plift build-apps a=my_app
# 4. Run database migrations
plift migrate-databases
# 5. Start your app
plift start-apps a=my_app
# 6. Verify it's running
plift status
plift logs c=my_app
# 7. Access your app
curl https://my-app.plift.local
# 8. Check monitoring
open http://localhost:3000 # Grafana
open http://localhost:9090 # Prometheus
Framework-Specific Notes¶
Laravel/Symfony (PHP)¶
- Ensure
composer.jsonexists in your app directory - PLift will auto-install Composer if not present
- PHP extensions are installed automatically based on config
.envfile is generated automatically
Django (Python)¶
- Ensure
requirements.txtexists - Database migrations run via Django's migration system
ALLOWED_HOSTSis automatically configured- Gunicorn is used as the WSGI server
Node.js¶
- Ensure
package.jsonexists node_modulesshould be in anonymous volume to persist- OpenTelemetry requires
tracing.jsfile (see examples) - Hot reload works with nodemon in development
Java/Spring Boot¶
- Build JAR file before adding to PLift
- OpenTelemetry Java agent is auto-downloaded
- Actuator endpoints are pre-configured
application.propertiesis generated automatically
Getting Help¶
- Check existing example apps in
apps/example_* - Review generated configs in
generated_configs/ - Check Salt templates in
salt/actions/generate/templates/ - View logs:
plift logs c=container_name