¡Esta es una revisión vieja del documento!
# Nueva Aplicación Flask - Parte 2 - Producción ## Introduction
Tutorial de Desarrollo de una Aplicación con Flask y Gestión con systemd
Referencias: [Flask mega tutorial](https://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-i-hello-world)
## Preparación del Entorno de Producción en Linux Ubuntu
### Instalación de Dependencias
En tu máquina de producción con Linux Ubuntu, instala las dependencias necesarias:
```bash sudo apt update sudo apt install python3-pip nginx pipenv sudo systemctl enable nginx ```
### Creamos directorio de producción.
```bash mkdir /var/www/my_flask_app sudo chown -R www-data:www-data /var/www/my_flask_app sudo chmod -R 755 /var/www/my_flask_app ```
Debemos copiar todos los ficheros necesarios a nuevo entorno de producción.
### Configuración de Nginx
Configura Nginx para servir la aplicación Flask. Crea un nuevo archivo de configuración en `/etc/nginx/sites-available/my_flask_app`:
```nginx server {
listen 80; server_name your_domain; access_log /var/log/nginx/my_flask_app.access.log; error_log /var/log/nginx/my_flask_app.error.log;
location / {
proxy_pass http://unix:/var/www/my_flask_app/my_flask_app.sock;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
} ```
* server_name is where the domain name goes. That is what you will use to access the web application. * access\_log and error\_logs specify the path to the access and error logs. * location block is where Nginx reverses proxy back to the Flask application.
Enable the website by creating a link to the sites-enabled directory. Reinicia Nginx:
```bash sudo ln -s /etc/nginx/sites-available/my_flask_app /etc/nginx/sites-enabled sudo nginx -t sudo systemctl restart nginx sudo systemctl status nginx ```
### Instalación de Gunicorn
Instala Gunicorn en el entorno virtual de producción. Se debe ejecutar export `PIPENV_VENV_IN_PROJECT=1` antes de hacer el pipenv install en el servidor, o el servicio de systemd fallará al no encontrar la ruta de Gunicorn.
```bash pipenv install gunicorn ```
While you are in the virtual environment check the path of gunicorn. Take note of this path. You will need to know the path to gunicorn to configure the systemd service file. My path is `/var/www/my_flask_app/.venv/bin/gunicorn`.
```bash $ which gunicorn ```
``` /var/www/my_flask_app/.venv/bin/gunicorn ```
### Testing with gunicorn
If you were able to run the Flask development server successfully use this command to test run the application using Gunicorn.
```bash gunicorn –workers 4 –bind 0.0.0.0:5000 wsgi:app ```
* –workers N: Set the –workers to two times the number of cores in your server. Adjust the number later if you have any issues. Do not exceed 12. * –bind 0.0.0.0:5000: This will listen on all server networking interfaces on port 5000. * wsgi:app: wsgi is the file name without the .py extension. app is the instance of the Flask application within the file. You should see the similar output below.
```bash $ gunicorn –workers 4 –bind 0.0.0.0:5000 wsgi:app ```
```text [2024-02-20 20:57:21 -0500] [4936] [INFO] Starting gunicorn 21.2.0 [2024-02-20 20:57:21 -0500] [4936] [INFO] Listening at: http://0.0.0.0:5000 (4936) [2024-02-20 20:57:21 -0500] [4936] [INFO] Using worker: sync [2024-02-20 20:57:21 -0500] [4937] [INFO] Booting worker with pid: 4937 […] ```
Press CTRL+C to stop the Gunicorn server.
While you are in the virtual environment check the path of gunicorn. Take note of this path. You will need to know the path to gunicorn to configure the systemd service file. My path is /var/www/my_flask_app/.venv/bin/gunicorn.
The path depends if you have PIPENV\_VENV\_IN\_PROJECT=true set in your .bashrc file or not. If the variable is set to true pipenv will use the .venv in your project directory.
—
## Alternativa Recomendada: Gestión Profesional de Permisos (User + Group)
En lugar de ceder toda la propiedad a `www-data`, utilizaremos un esquema de permisos compartidos. Esto permite que tu usuario edite archivos y ejecute `pipenv` sin usar `sudo`, mientras que `www-data` mantiene el acceso necesario para servir la aplicación.
### Configuración de Grupos
Añade tu usuario personal al grupo de Nginx para que ambos compartan privilegios:
```bash # Añadir el usuario actual al grupo www-data sudo usermod -aG www-data $USER ```
Nota: Se debe cerrar sesión y volver a entrar (o reiniciar el servidor) para que este cambio se aplique.
### Asignación de Propiedad y Bit de Grupo
Configuramos tu usuario como propietario y `www-data` como grupo responsable. Aplicaremos el setgid bit, que garantiza que cualquier archivo nuevo creado herede automáticamente el grupo `www-data`.
```bash # Cambiar propietario al usuario actual y grupo a www-data sudo chown -R $USER:www-data /var/www/my_flask_app
# Dar permisos de lectura/escritura/ejecución a dueño y grupo (775) sudo find /var/www/my_flask_app -type d -exec chmod 775 {} + sudo find /var/www/my_flask_app -type f -exec chmod 664 {} +
# Aplicar el bit de grupo persistente (setgid) sudo chmod g+s /var/www/my_flask_app
```
### Ajuste del Socket en Gunicorn
Para que Nginx pueda comunicarse con el socket creado por Gunicorn sin errores de “Permission Denied”, es fundamental añadir la máscara de permisos `-m 007` en la configuración del servicio.
Modifica tu archivo `/etc/systemd/system/my_flask_app.service`:
```ini [Service] … # El flag -m 007 asegura que el socket (.sock) sea creado con permisos rwxrwx— ExecStart=/var/www/my_flask_app/.venv/bin/gunicorn –workers 3 –bind unix:/var/www/my_flask_app/my_flask_app.sock -m 007 wsgi:app …
```
### Ventajas de este método
* Tu Usuario: Puedes usar `git pull`, `pipenv install` y editar código sin `sudo`. * Nginx / www-data: Grupo (rwx).r Puede leer archivos estáticos y escribir en el socket o logs. * Seguridad: Los usuarios que no pertenecen al grupo `www-data` no tienen acceso.
### Verificación de permisos
Para confirmar que la configuración es correcta, ejecuta:
```bash ls -la /var/www/my_flask_app
```
La salida debería mostrar los permisos como `drwxrwxr-x` y los dueños como `tu_usuario www-data`.
### Creación del Servicio systemd
Crea un archivo de servicio systemd para gestionar la aplicación. Crea un archivo `/etc/systemd/system/my_flask_app.service` con el siguiente contenido:
```ini [Unit] Description=Gunicorn instance to serve my_flask_app After=network.target
[Service] User=www-data Group=www-data WorkingDirectory=/var/www/my_flask_app Environment=“PATH=/var/www/my_flask_app/.venv/bin” Environment=“FLASK_ENV=production” Environment=“FLASK_APP=wsgi.py” ExecStart=/var/www/my_flask_app/.venv/bin/gunicorn –workers 3 –bind unix:/var/www/my_flask_app/my_flask_app.sock -m 007 wsgi:app
[Install] WantedBy=multi-user.target ```
* User: Sets the user who has permission to the project directory. * Group: Sets the group who has permission to the project directory. * Environment: Sets the path to the bin directory inside the virtual environment. * WorkingDirectory: Sets the base directory where the code for the project is. * ExecStart: Sets the path to the gunicorn executable inside the virtual environment along with the gunicorn command line options.
### Habilitar y Iniciar el Servicio
Habilita y inicia el servicio con los siguientes comandos:
```bash sudo systemctl enable my_flask_app sudo systemctl start my_flask_app ```
### Crear fichero de entorno
CD into the /var/www/my_flask_app directory.
```bash $ cd /var/www/my_flask_app ```
### /etc/hosts provisional
The Flask application is no longer accessible via the IP address since it is now being served by Gunicorn and Nginx. To access the Flask application you would need to use the name you set in the Nginx server block for the directive server_name in the Nginx configuration. To access the web page can edit the host file on your desktop/laptop to point the domain to the IP address of your server.
Edit the host file to add point the domain name to the server. Since my server's IP address is 192.168.12.34 I would add this line to the host file.
``` 192.168.12.34 my_flask_app ```
Host file location for Linux: `/etc/hosts`
Now I can access the Flask application with a browser via the name. `http://my_flask_app`.
You should see `Hello World` again.
Ahora la aplicación está probada y es posible modificar el DNS para que apunte a la dirección pública del servidor, volviendo a dejar el fichero `/etc/hosts` como estaba.
## Procedimiento de Actualización del Entorno de Producción
### Despliegue de Cambios
1. Actualiza el código en producción: Copia los archivos actualizados desde tu entorno de desarrollo a producción. Puedes usar `rsync` o un sistema de control de versiones como Git.
```bash rsync -avz –exclude 'venv/' /var/www/my_flask_app/ user@your_production_server:/path/to/production/project/ ```
2. Instala las dependencias: En el entorno de producción, asegúrate de que todas las dependencias estén actualizadas.
```bash cd /path/to/production/project pipenv install ```
3. Reinicia el Servicio: Reinicia el servicio systemd para aplicar los cambios.
```bash sudo systemctl restart my_flask_app ```
4. Reinicia Nginx: Asegúrate de que Nginx esté configurado correctamente y reinicia el servicio.
```bash sudo systemctl restart nginx ```