by Juan Ramón Gavilanes (jrgavilanes@gmail.com)
- 1.- Configuración inicial con Ubuntu Server
- 1.1.- Login como root.
- 1.2.- Crear nuevo usuario y escalarlo.
- 1.3.- Añadir clave pública de autentificación.
- 1.4.- Configurar demonio SSH: eliminar acceso de root.
- 1.5.- Configurar un firewall básico.
- 1.6.- Configurar zonas horarias y sincronización __N__etwork __T__ime __P__rotocol.
- 1.7.- Crear un archivo SWAP.
- 1.8.- Bibliografia
- 2.- Servidores Web
- 2.1.- Nginx
- 2.2.- Mysql y PHP
- 2.3.- Bibliografía
- 3.-Más aplicaciones
- 3.1.- Node js
- 3.2.- Wordpress
- 3.3.- Laravel
- 3.4.- Bibliografía
- 4.- Seguridad
- 4.1.- Actualizar sistema
- 4.2.- Crear e instalar certificado SSL
- 4.3.- Bibliografía
- 5.- Otros
local$: ssh root@SERVER_IP_ADDRESS
¿Quieres saber más sobre cómo conectar con tu servidor con SSH?
# adduser janrax
# gpasswd -a janrax sudo
Si queremos volver a cambiar la clave de usuario, escribiremos:
# sudo passwd janrax
Genera par de claves en tu máquina local ( si no tienes ninguna todavía )
local$: ssh-keygen -t rsa -b 4096
Asumiendo que su usuario es localuser está será la salida generada por el comando:
ssh-keygen output
Generating public/private rsa key pair.
Enter file in which to save the key (/Users/localuser/.ssh/id_rsa):
Recuerda que no hay que compartir la clave privada con nadie!!
Después de generar el par de claves SSH, debes copiar la clave pública a tu nuevo servidor.
local$: ssh-copy-id janrax@SERVER_IP_ADDRESS
En el servidor y conectados como root, editarmos el archivo de configuración de SSH y bloqueamos el acceso de root por ssh.
vi /etc/ssh/sshd_config
| /etc/ssh/sshd_config |
|---|
| PermitRootLogin no |
Si queremos forzar la conexión ssh usando sólo claves privadas, evitando por tanto, la conexión por password abierto, deberemos cambiar el siguiente parámetro:
| /etc/ssh/sshd_config |
|---|
| PasswordAuthentication no |
Tras realizar las modificaciones deseadas, salvamos y reiniciamos el servicio # service ssh restart
Antes de desconectar nuestra sesión como root, abrimos otro terminal y comprobamos que el nuevo usuario conecta correctamente. Si necesitamos escalar privilegios con el nuevo usuario, sólo debemos incluir la palabra sudo al inicio del comando.
Combo: Si además queremos proteger nuestra conexión de SSH de ataques de fuerza bruta, podemos instalar fail2ban:
sudo apt-get update
sudo apt-get install fail2ban
sudo systemctl start fail2ban
sudo systemctl enable fail2ban
sudo fail2ban-client status
Por defecto, baneará (expulsará:) 10 minutos al usuario que se equivoque 3 veces al introducir su password en un período de 10 minutos.
¿Quieres saber más sobre cómo proteger SSH?
Ubuntu incorpora de serie una herramienta llamada ufw, para configurar las políticas de firewall. Nuestra estrategia básica será bloquear por defecto todo lo que no necesitemos.
El demonio SSH corre por defecto en el puerto 22, y ufw permite referenciarlo por nombre:
sudo ufw allow ssh
En caso en que hayamos modificado el puerto por el que está escuchando, habrá que referenciar el puerto junto con el protocolo:
sudo ufw allow 4444/tcp
Si queremos ejecutar un servidor HTTP convecional, necesitaremos abrir el puerto 80:
sudo ufw allow 80/tcp
Si queremos que el servidor tenga SSL/TSL activado, también deberemos permitir el tráfico en su puerto:
sudo ufw allow 443/tcp
Necesitas correo SMTP?
sudo ufw allow 25/tcp
Quieres cerrar un puerto abierto?
sudo deny 25/tcp
Una vez tengamos las excepciones, las podemos revisar escribiendo:
sudo ufw show added
Si todo está ok, podemos activar el firewall escribiendo:
sudo ufw enable
Este comando bloqueará el tráfico a los puertos, instalará las excepciones que hemos indicado y configurará el servicio para que arranque automáticamente siempre que lo haga el servidor.
¿Quieres saber más sobre configuración avanzada del firewall?
Ejecuta el siguiente comando para establecer la zona horaria que quieres para el servidor.
sudo dpkg-reconfigure tzdata
Alternativa para configurar hora por comando desatendido
echo "Europe/Madrid" > /etc/timezone && ln -sf /usr/share/zoneinfo/Europe/Madrid /etc/localtimeConfigurar sincronización NTP, para sincronizar la hora con otros servidores de Internet.
sudo apt-get update
sudo apt-get install ntp
¿Quieres saber más sobre NTP?
El tamaño que debe tener un espacio SWAP depende de la situación, pero el doble de la memoria RAM disponible es un buen punto de partida. Si queremos que tenga __4 G__igas este es el comando a ejecutar:
sudo fallocate -l 4G /swapfile
Restringimos el acceso para que otros usuarios o procesos no puedan afectarle
sudo chmod 600 /swapfile
Formateamos el archivo como swap
sudo mkswap /swapfile
Lo activamos
sudo swapon /swapfile
Guardamos configuración para que inicie automáticamente al arrancar el sistema.
sudo sh -c 'echo "/swapfile none swap sw 0 0" >> /etc/fstab'
- Initial Server Setup with Ubuntu 14.04
- Additional Recommended Steps for New Ubuntu 14.04 Servers
- How To Protect SSH with Fail2Ban on Ubuntu 14.04
- 7 Security Measures to Protect your Servers
- How To Choose an Effective Backup Strategy for your VPS
- How To Use SFTP to Securely Transfer Files with a Remote Server
Instalación:
sudo apt-get update
sudo apt-get install nginx
Comprobamos el acceso desde el navegador web. Si necesitamos la dirección pública de la máquina, ejecutamos:
ip addr show eth0 | grep inet | awk '{ print $2; }' | sed 's/\/.*$//'
Manejando el proceso Nginx:
Detener el servidor web:
sudo service nginx stop
Arrancar el servidor web:
sudo service nginx start
Reiniciar el servidor web:
sudo service nginx restart
Nos aseguramos que el servidor web iniciará automáticamente al arrancar el servidor:
sudo update-rc.d nginx defaults
Configuramos el directorio Document root, que por defecto, está en /usr/share/nginx/html para dejarlo en /var/www
//En este ejemplo configuramos la esctructura de directorio para alojar dos sitios web.
sudo mkdir -p /var/www/example.com/html
sudo mkdir -p /var/www/test.com/html
//Le damos privilegios a nuestro usuario regular.
sudo chown -R $USER:$USER /var/www/example.com/html
sudo chown -R $USER:$USER /var/www/test.com/html
//Aseguramos que los permisos de la raíz sean los correctos.
sudo chmod -R 755 /var/www
Creamos los archivos Server Block
sudo cp /etc/nginx/sites-available/default /etc/nginx/sites-available/example.com
Editamos el nuevo archivo example.com, y lo dejamos así:
server {
listen 80 default_server;
listen [::]:80 default_server ipv6only=on;
root /var/www/example.com/html;
index index.html index.htm;
server_name example.com www.example.com;
location / {
try_files $uri $uri/ =404;
}
}
Activamos el nuevo Server Block y reiniciamos el servidor.
sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/
Ya estaríamos sirviendo nuestro nuevo sitio web, sin embargo, nos queda por hacer unos sencillos ajustes:
//Eliminamos el enlace del sitio que se crea por defecto.
sudo rm /etc/nginx/sites-enabled/default
Descomentamos un parámetro en el archivo de configuración de nginx
| /etc/nginx/nginx.conf |
|---|
| server_names_hash_bucket_size 64; |
Reiniciamos nginx ``` sudo service nginx restart ```
Por defecto el archivo LOG se almacena en:
/var/log/nginx/error.log
sudo apt-get update
sudo apt-get install mysql-server
//Generamos la estructura de directorios:
sudo mysql_install_db
//Protegemos la base de datos corriendo este script de seguridad
sudo mysql_secure_installation
sudo apt-get install php5-fpm php5-mysql php5-cli php5-mcrypt
//Si planeamos ejecutar wordpress añadir: -> php5-gd libssh2-php
Configuramos el archivo de configuración de PHP para hacerlo más seguro. Buscamos el parámetro cgi.fix_pathinfo, lo descomentamos y ponemos su valor a 0.
| /etc/php5/fpm/php.ini |
|---|
| cgi.fix_pathinfo=0 |
Y ahora reiniciamos el procesador PHP ``` sudo service php5-fpm restart ``` #### Configuración de Nginx para usar PHP Abrimos el Server Block del la aplicación que queremos que ejecute PHP, y lo dejamos así, realizando los cambios pertinentes al arrea de __root__, y __server_name__.
sudo vi /etc/nginx/sites-available/default
server {
listen 80 default_server;
listen [::]:80 default_server ipv6only=on;
root /usr/share/nginx/html;
index index.php index.html index.htm;
server_name server_domain_name_or_IP;
location / {
try_files $uri $uri/ =404;
}
error_page 404 /404.html;
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
Reiniciamos el servicio
sudo service nginx restart
Probamos el servidor cargando un archivo .php con la función phpinfo();
- How To Install Nginx on Ubuntu 14.04 LTS
- How To Set Up Nginx Server Blocks (Virtual Hosts) on Ubuntu 14.04 LTS
- How To Install Apache Tomcat 7 on Ubuntu 14.04 via Apt-Get
- How To Set Up Apache Virtual Hosts on Ubuntu 14.04 LTS
- Introduction to Nginx and LEMP on Ubuntu 14.04
- How To Upgrade to PHP 7 on Ubuntu 14.04
Hay varios métodos, ver bibliografía, pero el que más me ha gustado es instalarlo a través de NVM, ya que permite tener varios sistemas instalados y elegir cual usar.
Se instala así:
sudo apt-get update
sudo apt-get install build-essential libssl-dev
Ahora hay que obtener el script de instalación más actual desde la página github del desarrollador. A día de hoy el siguiente script es el más actual:
curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.29.0/install.sh | bash
Una vez instalado, cerramos la sesión y la volvemos a arrancar.
El siguiente comando nos permite elegir que versión de node queremos instalar:
nvm ls-remote
...
iojs-v3.0.0
iojs-v3.1.0
iojs-v3.2.0
iojs-v3.3.0
iojs-v3.3.1
v4.0.0
v4.1.0
v4.1.1
v4.1.2
v4.2.0
Si queremos instalar la última en nuestro sistema, ejecutamos:
nvm install 4.2.0
Para ver la versión de node que estamos usando ahora mismo escribimos:
node -v
Para ver las versiones que tenemos instaladas en nuestro sistema:
nvm ls
Para cambiar a otra versión que tengamos instalada:
nvm use 0.11.13
Para establecer una versión por defecto:
nvm alias default 4.2.0
nvm use default
Preparación:
sudo apt-get update && apt-get upgrade
Instalación
sudo apt-get install php5-fpm php5-mysql php5-cli php5-mcrypt
Configuramos Nginx
sudo mkdir /var/www/laravel
sudo vi /etc/nginx/sites-available/laravel
Y copiamos esto:
server {
listen 80;
root /var/www/laravel/public/;
index index.php index.html index.htm;
server_name laravel.jrgware.test www.laravel.jrgware.test;
location / {
try_files $uri $uri/ /index.php$is_args$args;
}
# pass the PHP scripts to FastCGI server listening on /var/run/php5-fpm.sock
location ~ \.php$ {
try_files $uri /index.php =404;
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
Activamos el sitio:
sudo ln -s /etc/nginx/sites-available/laravel /etc/nginx/sites-enabled/
Configuramos PHP
Editamos su archivo de configuración:
sudo vi /etc/php5/fpm/php.ini
Buscamos la linea cgi.fix_pathinfo y la dejamos así:
cgi.fix_pathinfo=0
Ahora editamos:
sudo vi /etc/php5/fpm/pool.d/www.conf
Si existe esta linea:
listen = 127.0.0.1:9000
la sustituimos por esta:
listen = /var/run/php5-fpm.sock
Salvamos todos los cambios y reiniciamos servicios:
sudo service php5-fpm restart
sudo service nginx restart
Configuramos Composer
sudo curl -sS https://getcomposer.org/installer | php
sudo mv composer.phar /usr/local/bin/composer
Ya podemos instalar Laravel
sudo composer create-project laravel/laravel /var/www/laravel/
Para finalizar establecemos los permisos de la carpeta
sudo chgrp -R www-data /var/www/laravel
sudo chmod -R 775 /var/www/laravel/storage
- How To Install Node.js on an Ubuntu 14.04 server
- How To Install WordPress with Nginx on Ubuntu 14.04
- How To Install Laravel with Nginx on an Ubuntu 12.04 LTS VPS
$ sudo apt-get update
$ sudo apt-get upgrade
$ sudo shutdown -r now //reiniciar servidor.
$ sudo mkdir /etc/nginx/ssl
$ sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/nginx/ssl/nginx.key -out /etc/nginx/ssl/nginx.crt
//el campo más importante es (e.g. server FQDN or YOUR name), que debe ser el nombre del dominio o la ip pública del servidor.
// /etc/nginx/sites-available/my-server-block
server {
listen 80 default_server;
listen [::]:80 default_server ipv6only=on;
listen 443 ssl; // <-- Línea añadida
root /usr/share/nginx/html;
index index.html index.htm;
server_name your_domain.com;
ssl_certificate /etc/nginx/ssl/nginx.crt; // <-- Línea añadida
ssl_certificate_key /etc/nginx/ssl/nginx.key; // <-- Línea añadida
location / {
try_files $uri $uri/ =404;
}
}
$ sudo service nginx restart
Para que nuestro certificado esté avalado por una entidad y no muestre mensajes preocupantes en los navegadores, podemos usar los servicios de Let's Encrypt, mirar en bibliografía el articulo que lo explica detalladamente.
- How To Create an SSL Certificate on Nginx for Ubuntu 14.04
- Updating Ubuntu 14.04 -- Security Updates
- How To Secure Nginx with Let's Encrypt on Ubuntu 14.04
$ wget -O speedtest-cli https://raw.github.com/sivel/speedtest-cli/master/speedtest_cli.py
$ chmod +x speedtest-cli
$ ./speedtest-cli
Utilizamos el siguiente comando:
dpkg --get-selections
Gracias a este herramienta también es posible exportar la lista de paquetes instalados:
dpkg --get-selections > mis_paquetes
Luego podemos instalarlos en otra máquina:
dpkg --set-selections < mis_paquetes
apt-get dselect-upgrade
El comando dpkg –l da la lista de paquetes instalados pero con mayor información. Sin embargo, no es posible utilizarlo para instalar una lista de paquetes.
file: /etc/rc.local
#!/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.
docker start rstudio1 && docker exec -it rstudio1 bash arrancaservicios.sh
docker start rstudio2
exit 0
instalar
$ sudo apt-get install openssh-server$ ifconfig -a
...
enp0s8: flags=4098<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
ether 08:00:27:e5:78:0f txqueuelen 1000 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
...
$ cat /etc/network/interfaces
auto lo
iface lo inet loopback
auto enp0s8
iface enp0s8 inet static
address 192.168.56.100
$ cat /etc/hostname
apihub
cat /etc/hosts
127.0.0.1 localhost
127.0.1.1 MateBook
# The following lines are desirable for IPv6 capable hosts
::1 ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
192.168.56.100 apihub
192.168.56.101 app1
192.168.56.102 app2
192.168.56.110 central1
ssh-keygen -t rsa -b 4096$ ssh-copy-id janrax@servidor # desde cliente
$ scp /home/janrax/.ssh/id_rsa.pub janrax@server:/home/janrax/.ssh/uploaded_key.pub
# en servidor
$ cat /home/janrax/.ssh/uploaded_key.pub >> /home/janrax/.ssh/authorized_keys
$ chmod 700 /home/janrax/.ssh
$ chmod 600 /home/janrax/.ssh/*$ cat vi /etc/ssh/sshd_config
...
PasswordAuthentication no
...
$ sudo service ssh restart
sudo apt-get install docker.io docker-compose docker-buildx
sudo groupadd docker
sudo usermod -aG docker $USER
sudo rebootInstalar cluster local ( minikube )
https://minikube.sigs.k8s.io/docs/start/
Recuerda poner esto .bashrc
alias kubectl="minikube kubectl --"
minikube start
minikube dashboard --url
minikube stop
minikube status
kubectl run miapp --image=jrgavilanes/mi_nginx --port 8080
kubectl get pods
kubectl describe pod miapp
kubectl expose pod miapp --type=LoadBalancer --port=8080 --target-port=80
kubectl get services
kubectl describe service miapp
minikube service --url miapp ( me devuelve la url exterior )
janrax@janrax-matebook:~/Escritorio/Code/mi-kubernetes$ echo -n "clave_codificada" | base64
Y2xhdmVfY29kaWZpY2FkYQ==
janrax@janrax-matebook:~/Escritorio/Code/mi-kubernetes$ echo 'Y2xhdmVfY29kaWZpY2FkYQ==' | base64 --decode
clave_codificadadocker run debian ping google.es
docker run -it debian /bin/bash
docker images
docker ps -a
docker create debian # devuelve container_id
docker start <container_id>
docker logs <container_id>
docker stop <container_id>
docker kill <container_id>
docker start -a <container_id>
docker exec -it <container_id> /bin/bash
# Cuánto ocupa y borra datos
docker system df -v
docker system prune -a
# Borrar volumes
docker volume prune
FROM debian
RUN apt update
CMD ["ping", "google.es"]
docker build -f Dockerfile . # Si no pones -f va por defecto a Dockerfile
docker build -t jrgavilanes/proyecto:version .
docker commit -c 'CMD ["ping", "google.es"]' <container_id>
docker run -p 5000:8080 <imagen_id>
Ejemplo de guay:
# Dockerfile
FROM debian
RUN apt update
RUN apt install -y python3 python3-pip
WORKDIR /app
CMD ["python3", "-m", "http.server"]
Rúlalo
docker -t imagen_juanra build .
docker run --name contenedor_juanra -p 5000:8000 imagen_juanra
curl localhost:5000
docker run -it -v $(pwd):/app alpine shdockerfile alpine con ssh
# Dockerfile.apihub
FROM alpine
RUN apk update
RUN apk add openssh
RUN ssh-keygen -A
RUN adduser --disabled-password --gecos "" juanra
RUN echo "juanra:juanra" | chpasswd
WORKDIR /app
COPY app.sh .
CMD ["sh", "app.sh"]
docker-compose.yml
version: '3'
services:
apihub:
build:
context: .
dockerfile: Dockerfile.apihub
app1:
build:
context: .
dockerfile: Dockerfile.apihub
docker-compose up
docker-compose up --build
docker-compose down
docker build -f Dockerfile.apihub -t jrgavilanes/apihub .
docker run -v $(pwd):/app --name apihub jrgavilanes/apihub
PING google.es (216.58.201.163): 56 data bytes
64 bytes from 216.58.201.163: seq=0 ttl=48 time=27.577 ms
64 bytes from 216.58.201.163: seq=1 ttl=48 time=65.366 ms
...
docker start apihub
apihub
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
14b76d451e34 jrgavilanes/apihub "ping google.es" 38 seconds ago Up 8 seconds apihub
docker logs apihub
PING google.es (216.58.201.163): 56 data bytes
64 bytes from 216.58.201.163: seq=0 ttl=48 time=27.577 ms
64 bytes from 216.58.201.163: seq=1 ttl=48 time=65.366 ms
64 bytes from 216.58.201.163: seq=2 ttl=48 time=248.764 ms
64 bytes from 216.58.201.163: seq=3 ttl=48 time=67.446 ms
docker stop apihub # En 10 segundos hace kill
docker kill apihub # Recomendado stop
#!/bin/bash
# Habilitar modo estricto para manejar errores
set -e
echo "🚀 Iniciando instalación de entorno de desarrollo en LMDE..."
# 1️⃣ Actualizar el sistema
echo "🔄 Actualizando paquetes..."
sudo apt update && sudo apt upgrade -y
# 2️⃣ Instalar Apache
echo "🌐 Instalando Apache..."
sudo apt install -y apache2
sudo systemctl enable apache2
sudo systemctl start apache2
# 3️⃣ Instalar MySQL
echo "💾 Instalando MySQL Server..."
sudo apt install -y default-mysql-server
sudo systemctl enable mysql
sudo systemctl start mysql
# 4️⃣ Instalar PHP y extensiones necesarias
echo "🐘 Instalando PHP 8.2 y extensiones requeridas..."
sudo apt install -y php php-cli php-mbstring php-xml php-bcmath php-curl php-zip php-tokenizer php-common php-intl php-mysql php-gd libapache2-mod-php unzip curl htop vim
# Verificar instalación de PHP
php -v
# 5️⃣ Instalar Composer (gestor de dependencias PHP)
echo "📦 Instalando Composer..."
curl -sS https://getcomposer.org/installer | php
sudo mv composer.phar /usr/local/bin/composer
composer -V
# 6️⃣ Instalar Laravel Installer
echo "🌟 Instalando Laravel Installer..."
composer global require laravel/installer
# 7️⃣ Agregar Laravel al PATH
echo "🔧 Configurando Laravel Installer en el PATH..."
echo 'export PATH="$HOME/.config/composer/vendor/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc
# 8️⃣ Verificar instalación de Laravel
echo "🛠️ Verificando instalación de Laravel..."
laravel --version
# 9️⃣ Instalar Node.js y npm
echo "📦 Instalando Node.js y npm..."
sudo apt install -y nodejs npm
node -v
npm -v
# 🔟 Configurar permisos para Apache (Opcional, si usarás /var/www)
echo "🔧 Configurando permisos para Apache..."
sudo usermod -aG www-data $USER
sudo chown -R www-data:www-data /var/www
sudo chmod -R 775 /var/www
# Instalar Visual Studio Code
sudo apt update
sudo apt install -y wget gpg
wget -qO- https://packages.microsoft.com/keys/microsoft.asc | sudo tee /usr/share/keyrings/microsoft.asc
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/microsoft.asc] https://packages.microsoft.com/repos/code stable main" | sudo tee /etc/apt/sources.list.d/vscode.list
sudo apt update
sudo apt install -y code
# Instalar DBeaver
wget https://dbeaver.io/files/dbeaver-ce_latest_amd64.deb && sudo dpkg -i dbeaver-ce_latest_amd64.deb && rm dbeaver-ce_latest_amd64.deb
# Instalar Docker
sudo apt-get install docker.io docker-compose -y && sudo usermod -aG docker $USER
# 1️⃣1️⃣ Reiniciar Apache para aplicar cambios
echo "🔄 Reiniciando Apache..."
sudo systemctl restart apache2
# 1️⃣2️⃣ Mensaje final
echo "✅ Instalación completa. Tu entorno está listo para programar con Laravel en LMDE."
echo "👉 Recuerda configurar MySQL con: sudo mysql_secure_installation"
echo "👉 Para crear un nuevo proyecto usa: laravel new miapp"
echo "👉 Para probar Laravel: php artisan serve"
exit 0