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