v1
This commit is contained in:
commit
23b08fb56b
27
Lenvi.yaml
Normal file
27
Lenvi.yaml
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
# ------------------------------------------------------------------
|
||||||
|
# Lenvi: Central Configuration for Your Development Environment
|
||||||
|
# ------------------------------------------------------------------
|
||||||
|
|
||||||
|
# 1. Set the global database engine.
|
||||||
|
# Choose one: "mariadb", "mysql", or "postgres"
|
||||||
|
db_engine: "mariadb"
|
||||||
|
|
||||||
|
# 2. Define all your Laravel sites below.
|
||||||
|
# Add, edit, or remove sites as needed.
|
||||||
|
sites:
|
||||||
|
- domain: myapp.local
|
||||||
|
project_root: /home/mar/projects/myapp
|
||||||
|
php_version: "8.2"
|
||||||
|
|
||||||
|
- domain: legacy-app.local
|
||||||
|
project_root: /home/mar/projects/legacy-app
|
||||||
|
php_version: "8.0"
|
||||||
|
|
||||||
|
- domain: another-project.local
|
||||||
|
project_root: /home/mar/projects/another-project
|
||||||
|
php_version: "8.2"
|
||||||
|
|
||||||
|
# Example of a new project you might add later:
|
||||||
|
# - domain: new-api.local
|
||||||
|
# project_root: /home/mar/projects/new-api
|
||||||
|
# php_version: "8.3"
|
54
README.md
Normal file
54
README.md
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
# Lenvi Ansible Provisioner
|
||||||
|
|
||||||
|
Lenvi is a lightweight, Ansible-powered tool for managing local Laravel development environments. It provides a Homestead-like experience without the overhead of a virtual machine, running natively on Linux or on Windows via WSL2.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- **Centralized Configuration:** Manage all your projects from a single `lenvi.yaml` file.
|
||||||
|
- **Multi-PHP:** Assign a specific PHP version (e.g., 8.0, 8.2, 8.3) to each site.
|
||||||
|
- **Database Support:** Automatically creates databases using a shared MariaDB, MySQL, or PostgreSQL server.
|
||||||
|
- **Idempotent:** Safely run the provisioner at any time to update your environment.
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
1. **Ansible:** You must have Ansible installed.
|
||||||
|
```bash
|
||||||
|
# On Debian/Ubuntu
|
||||||
|
sudo apt update
|
||||||
|
sudo apt install python3-pip -y
|
||||||
|
pip3 install ansible
|
||||||
|
```
|
||||||
|
2. **WSL2 (for Windows users):** Install WSL2 and a Linux distribution like **Ubuntu 22.04** from the Microsoft Store. All subsequent commands must be run from the WSL2 terminal.
|
||||||
|
|
||||||
|
## How to Use
|
||||||
|
|
||||||
|
1. **Clone this repository:**
|
||||||
|
```bash
|
||||||
|
git clone <your-repo-url> ~/tools/lenvi_ansible
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Configure `lenvi.yaml`:**
|
||||||
|
Open `~/tools/lenvi_ansible/lenvi.yaml` and configure it for your projects. Set your `db_engine` and list all your sites under the `sites` key.
|
||||||
|
|
||||||
|
3. **Run the Playbook:**
|
||||||
|
Navigate to the `lenvi_ansible` directory and run the main playbook.
|
||||||
|
```bash
|
||||||
|
cd ~/tools/lenvi_ansible
|
||||||
|
ansible-playbook playbook.yml --ask-become-pass
|
||||||
|
```
|
||||||
|
Ansible will ask for your `sudo` password to install software and configure services.
|
||||||
|
|
||||||
|
### Important Note for Windows (WSL2) Users
|
||||||
|
|
||||||
|
For your Windows browser (Chrome, Firefox, etc.) to access a site like `myapp.test`, you must manually edit the **Windows hosts file**.
|
||||||
|
|
||||||
|
1. Open **Notepad** as an **Administrator**.
|
||||||
|
2. Open the file: `C:\Windows\System32\drivers\etc\hosts`
|
||||||
|
3. For each site in your `lenvi.yaml`, add a new line:
|
||||||
|
```
|
||||||
|
127.0.0.1 myapp.test
|
||||||
|
127.0.0.1 another-app.test
|
||||||
|
```
|
||||||
|
4. Save the file. You only need to do this once per new domain.
|
||||||
|
|
||||||
|
You can now access your sites in your browser!
|
3
ansible.cfg
Normal file
3
ansible.cfg
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
[defaults]
|
||||||
|
inventory = inventory
|
||||||
|
host_key_checking = False
|
19
playbook.yml
Normal file
19
playbook.yml
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
---
|
||||||
|
- name: "Provision Lenvi Development Environment"
|
||||||
|
hosts: lenvi_dev
|
||||||
|
become: yes
|
||||||
|
|
||||||
|
vars_files:
|
||||||
|
- Lenvi.yaml
|
||||||
|
|
||||||
|
pre_tasks:
|
||||||
|
- name: "Gather a unique list of required PHP versions from sites"
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
php_versions_to_install: "{{ sites | map(attribute='php_version') | list | unique }}"
|
||||||
|
|
||||||
|
roles:
|
||||||
|
- role: common
|
||||||
|
- role: database
|
||||||
|
- role: php
|
||||||
|
- role: nginx
|
||||||
|
- role: projects
|
14
roles/common/tasks/main.yml
Normal file
14
roles/common/tasks/main.yml
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
---
|
||||||
|
- name: "Install common dependencies"
|
||||||
|
ansible.builtin.apt:
|
||||||
|
name:
|
||||||
|
- software-properties-common
|
||||||
|
- ca-certificates
|
||||||
|
- apt-transport-https
|
||||||
|
state: present
|
||||||
|
update_cache: yes
|
||||||
|
|
||||||
|
- name: "Add Ondřej PPA for PHP"
|
||||||
|
ansible.builtin.apt_repository:
|
||||||
|
repo: "ppa:ondrej/php"
|
||||||
|
state: present
|
30
roles/database/tasks/main.yml
Normal file
30
roles/database/tasks/main.yml
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
---
|
||||||
|
- name: "Install MariaDB/MySQL server"
|
||||||
|
ansible.builtin.apt:
|
||||||
|
name: mariadb-server
|
||||||
|
state: present
|
||||||
|
update_cache: yes
|
||||||
|
when: db_engine == 'mariadb' or db_engine == 'mysql'
|
||||||
|
|
||||||
|
- name: "Install PostgreSQL server"
|
||||||
|
ansible.builtin.apt:
|
||||||
|
name:
|
||||||
|
- postgresql
|
||||||
|
- postgresql-contrib
|
||||||
|
state: present
|
||||||
|
update_cache: yes
|
||||||
|
when: db_engine == 'postgres'
|
||||||
|
|
||||||
|
- name: "Ensure MariaDB/MySQL service is running and enabled"
|
||||||
|
ansible.builtin.service:
|
||||||
|
name: mariadb
|
||||||
|
state: started
|
||||||
|
enabled: yes
|
||||||
|
when: db_engine == 'mariadb' or db_engine == 'mysql'
|
||||||
|
|
||||||
|
- name: "Ensure PostgreSQL service is running and enabled"
|
||||||
|
ansible.builtin.service:
|
||||||
|
name: postgresql
|
||||||
|
state: started
|
||||||
|
enabled: yes
|
||||||
|
when: db_engine == 'postgres'
|
5
roles/nginx/handlers/main.yml
Normal file
5
roles/nginx/handlers/main.yml
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
- name: "Reload Nginx"
|
||||||
|
ansible.builtin.service:
|
||||||
|
name: nginx
|
||||||
|
state: reloaded
|
17
roles/nginx/tasks/main.yml
Normal file
17
roles/nginx/tasks/main.yml
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
---
|
||||||
|
- name: "Install Nginx"
|
||||||
|
ansible.builtin.apt:
|
||||||
|
name: nginx
|
||||||
|
state: present
|
||||||
|
|
||||||
|
- name: "Ensure Nginx is enabled and started"
|
||||||
|
ansible.builtin.service:
|
||||||
|
name: nginx
|
||||||
|
state: started
|
||||||
|
enabled: yes
|
||||||
|
|
||||||
|
- name: "Remove the default Nginx site to prevent conflicts"
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: /etc/nginx/sites-enabled/default
|
||||||
|
state: absent
|
||||||
|
notify: Reload Nginx
|
28
roles/php/tasks/main.yml
Normal file
28
roles/php/tasks/main.yml
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
---
|
||||||
|
- name: "Install required PHP versions and extensions"
|
||||||
|
ansible.builtin.apt:
|
||||||
|
name:
|
||||||
|
# Core PHP
|
||||||
|
- "php{{ item }}"
|
||||||
|
- "php{{ item }}-fpm"
|
||||||
|
- "php{{ item }}-cli"
|
||||||
|
# Common Laravel Extensions
|
||||||
|
- "php{{ item }}-common"
|
||||||
|
- "php{{ item }}-mysql"
|
||||||
|
- "php{{ item }}-pgsql"
|
||||||
|
- "php{{ item }}-xml"
|
||||||
|
- "php{{ item }}-zip"
|
||||||
|
- "php{{ item }}-mbstring"
|
||||||
|
- "php{{ item }}-curl"
|
||||||
|
- "php{{ item }}-bcmath"
|
||||||
|
state: present
|
||||||
|
loop: "{{ php_versions_to_install }}"
|
||||||
|
when: php_versions_to_install is defined and php_versions_to_install | length > 0
|
||||||
|
|
||||||
|
- name: "Ensure all PHP-FPM services are enabled and started"
|
||||||
|
ansible.builtin.service:
|
||||||
|
name: "php{{ item }}-fpm"
|
||||||
|
enabled: yes
|
||||||
|
state: started
|
||||||
|
loop: "{{ php_versions_to_install }}"
|
||||||
|
when: php_versions_to_install is defined and php_versions_to_install | length > 0
|
7
roles/projects/handlers/main.yml
Normal file
7
roles/projects/handlers/main.yml
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
- name: "Reload PHP-FPM Services"
|
||||||
|
ansible.builtin.service:
|
||||||
|
name: "php{{ item }}-fpm"
|
||||||
|
state: reloaded
|
||||||
|
loop: "{{ php_versions_to_install }}"
|
||||||
|
when: php_versions_to_install is defined and php_versions_to_install | length > 0
|
8
roles/projects/tasks/configure_site.yml
Normal file
8
roles/projects/tasks/configure_site.yml
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
---
|
||||||
|
- name: "Create Nginx config for {{ project.domain }} in conf.d"
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: nginx-site.conf.j2
|
||||||
|
dest: "/etc/nginx/conf.d/{{ project.domain }}.conf"
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: '0644'
|
11
roles/projects/tasks/main.yml
Normal file
11
roles/projects/tasks/main.yml
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
---
|
||||||
|
# This loop will run the 'configure_site.yml' tasks for each site
|
||||||
|
# defined in Lenvi.yaml. Handlers are notified only once at the end.
|
||||||
|
- name: "Configure Nginx site for each project"
|
||||||
|
ansible.builtin.include_tasks: configure_site.yml
|
||||||
|
loop: "{{ sites }}"
|
||||||
|
loop_control:
|
||||||
|
loop_var: project
|
||||||
|
notify:
|
||||||
|
- Reload Nginx
|
||||||
|
- Reload PHP-FPM Services
|
92
roles/projects/templates/nginx-site.conf.j2
Normal file
92
roles/projects/templates/nginx-site.conf.j2
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name {{ project.domain }};
|
||||||
|
|
||||||
|
root {{ project.project_root }}/public;
|
||||||
|
index index.php;
|
||||||
|
|
||||||
|
access_log /var/log/nginx/{{ project.domain }}-access.log;
|
||||||
|
error_log /var/log/nginx/{{ project.domain }}-error.log;
|
||||||
|
|
||||||
|
# General performance
|
||||||
|
sendfile on;
|
||||||
|
tcp_nopush on;
|
||||||
|
tcp_nodelay on;
|
||||||
|
keepalive_timeout 30s;
|
||||||
|
types_hash_max_size 2048;
|
||||||
|
server_tokens off;
|
||||||
|
|
||||||
|
client_max_body_size 100M;
|
||||||
|
client_body_buffer_size 128k;
|
||||||
|
|
||||||
|
# Security headers
|
||||||
|
add_header X-Frame-Options "SAMEORIGIN";
|
||||||
|
add_header X-XSS-Protection "1; mode=block";
|
||||||
|
add_header X-Content-Type-Options "nosniff";
|
||||||
|
|
||||||
|
# Gzip compression
|
||||||
|
gzip on;
|
||||||
|
gzip_disable "msie6";
|
||||||
|
gzip_vary on;
|
||||||
|
gzip_proxied any;
|
||||||
|
gzip_comp_level 6;
|
||||||
|
gzip_buffers 16 8k;
|
||||||
|
gzip_http_version 1.1;
|
||||||
|
gzip_types
|
||||||
|
text/plain
|
||||||
|
text/css
|
||||||
|
text/xml
|
||||||
|
text/javascript
|
||||||
|
application/json
|
||||||
|
application/javascript
|
||||||
|
application/x-javascript
|
||||||
|
application/xml
|
||||||
|
application/xml+rss
|
||||||
|
font/ttf
|
||||||
|
font/otf
|
||||||
|
image/svg+xml;
|
||||||
|
|
||||||
|
# Laravel-friendly routing
|
||||||
|
location / {
|
||||||
|
try_files $uri $uri/ /index.php?$query_string;
|
||||||
|
}
|
||||||
|
|
||||||
|
# PHP-FPM handling
|
||||||
|
location ~ \.php$ {
|
||||||
|
include fastcgi_params;
|
||||||
|
fastcgi_pass unix:/run/php/php{{ project.php_version }}-fpm.sock;
|
||||||
|
fastcgi_index index.php;
|
||||||
|
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
|
||||||
|
fastcgi_param DOCUMENT_ROOT $realpath_root;
|
||||||
|
|
||||||
|
fastcgi_buffers 16 16k;
|
||||||
|
fastcgi_buffer_size 32k;
|
||||||
|
fastcgi_busy_buffers_size 64k;
|
||||||
|
fastcgi_temp_file_write_size 64k;
|
||||||
|
fastcgi_intercept_errors on;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Block hidden files
|
||||||
|
location ~ /\.(?!well-known).* {
|
||||||
|
deny all;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Static file caching
|
||||||
|
location ~* \.(jpg|jpeg|png|gif|ico|css|js|woff2?|ttf|svg|eot)$ {
|
||||||
|
expires 30d;
|
||||||
|
access_log off;
|
||||||
|
add_header Cache-Control "public";
|
||||||
|
}
|
||||||
|
|
||||||
|
# Maintenance mode redirect (Laravel down file)
|
||||||
|
if (-f $document_root/storage/framework/down) {
|
||||||
|
return 503;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Optional: Nginx status endpoint (local only)
|
||||||
|
location /nginx_status {
|
||||||
|
stub_status;
|
||||||
|
allow 127.0.0.1;
|
||||||
|
deny all;
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user