En este tutorial les mostrare como crear una librería para nuestras fotos. Entre muchas galerías webs que encontré la que más me llamo la atención fue KOKEN.
Koken es un CMS fácil de usar que presentará su trabajo fotográfico en unos pocos clics. Koken tiene muchas características como la gestión de colecciones, un sistema avanzado de etiquetas y categorías, una gestión privada de recursos (para compartir solo con su familia o sus clientes, por ejemplo), una sincronización con Lightroom y, por supuesto, muchas opciones para personalizar el tema y la navegación. Koken también tiene una tienda para agregar extensiones y así tener características adicionales.
Tambien ofrece varios temas que resaltan fácilmente sus fotos en alta calidad. Diseñado para cumplir con las restricciones actuales de la web, su sitio responderá y se adaptará a la resolución del usuario.
Este tutorial constituye una recopilación de muchos tutoriales que existen en internet, con un extra aportado por mí para aquellos que estamos detrás de un proxy. Bueno, manos a la obra.
NOTA: Para un mejor entendimiento del mismo y no tener que estar regresando a los pasos anteriores de la instalación, recomiendo que se lo lean todo primero.
1- Requisitos
Como siempre el entorno que usare será un contenedor de Proxmox usando como OS Debian 9.6 (también podemos usar Ubuntu). Al ser un web nuestro CT (contenedor) no necesitara de muchos recursos:
CPU: 2 cores
RAM: 2 GB RAM
HDD: 8 GB
1.1- Inicio
Comenzaremos preparando las condiciones para la instalación de nuestra web.
apt update apt upgrade apt install mc htop unzip
2- Nginx
apt install nginx
2.1- Configuracion de Nginx
Uno de los parámetros para ajustar es el worker_processes. Para aprovechar al máximo la potencia de su servidor, se recomienda poner tantos procesos de trabajo como núcleos disponibles en su servidor. Para encontrar el número de núcleos en su servidor, simplemente ejecute el comando:
root@webserv:~# grep processor /proc/cpuinfo | wc -l 2
Por razones de seguridad, se recomienda deshabilitar el envío de información, como el número de versión de su Nginx. Para hacer esto, descomente esta directiva en el bloque http o agréguela.
server_tokens off;
Modifique las siguientes directivas en el archivo de configuración Nginx /etc/nginx/nginx.conf:
nano /etc/nginx/nginx.conf ------------------------------------------------------------------------- user www-data; worker_processes auto; --------> poner el número de núcleos(worker_processes 2;) pid /run/nginx.pid; include /etc/nginx/modules-enabled/*.conf; events { worker_connections 768; # multi_accept on; } http { ## # Basic Settings ## sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 65; types_hash_max_size 2048; # server_tokens off; -------------> descomentar server_names_hash_bucket_size 64; # server_name_in_redirect off;
3- Descarga e instalacion de Koken
cd /var/www wget https://s3.amazonaws.com/koken-installer/releases/Koken_Installer.zip unzip Koken_Installer .zip
4- Usuarios y permisos
Durante la implementación básica de un servidor HTTP, el usuario bajo el que se ejecuta este servidor (Apache, Nginx …) es principalmente www-data, nobody o apache. Esto significa que, si existen varios sitios en la misma instancia de Nginx, todos usan el mismo usuario. Pero si uno de los sitios está dañado por un usuario malintencionado, el atacante puede aprovechar al máximo todos los derechos del usuario bajo el que se ejecuta el servidor web. Todos los sitios son por lo tanto vulnerables.
Por razones obvias de seguridad, se recomienda particionar a estos usuarios y tener un usuario dedicado para administrar la carpeta koken. Este usuario tendrá los derechos más limitados posible a este directorio.
adduser koken chown -R koken:www-data /var/www/koken/
5- PHP-FPM
Usaremos PHP 7.3 y PHP-FPM 7.3 también así como otras dependencias de PHP.
apt install apt-transport-https lsb-release ca-certificates
Agregamos la llave de repositorio y su enlace
wget -O /etc/apt/trusted.gpg.d/php.gpg https://packages.sury.org/php/apt.gpg sh -c 'echo "deb https://packages.sury.org/php/ $(lsb_release -sc) main" > /etc/apt/sources.list.d/php.list' apt update
Instalamos PHP 7.3
apt install -y php7.3 php7.3-common php7.3-cli php7.3-fpm php7.3-mysql php7.3-xml php7.3-curl php7.3-mbstring php7.3-zip ffmpeg pwgen graphicsmagick php-imagick php-mcrypt
Comprobamos.
php -v PHP 7.3.1-1+0~20190113101756.25+stretch~1.gbp15aaa9 (cli) (built: Jan 13 2019 10:17:57) ( NTS ) Copyright (c) 1997-2018 The PHP Group Zend Engine v3.3.1, Copyright (c) 1998-2018 Zend Technologies with Zend OPcache v7.3.1-1+0~20190113101756.25+stretch~1.gbp15aaa9, Copyright (c) 1999-2018, by Zend Technologies
5.1- Creacion del Pool Koken
Creamos el pool Koken dedicado, creando el siguiente archivo de configuración: /etc/php/7.3/fpm/pool.d/koken.conf
nano /etc/php/7.3/fpm/pool.d/koken.conf ______________________________________________________ [koken] listen = /var/run/koken.sock listen.owner = koken listen.group = www-data user = koken group = www-data pm = ondemand pm.max_children = 60 #valor que calculamos pm.process_idle_timeout = 60s pm.max_requests = 500 env[HOSTNAME] = $HOSTNAME env[PATH] = /usr/local/bin:/usr/bin:/bin env[TMP] = /tmp env[TMPDIR] = /tmp env[TEMP] = /tmp
[koken]: nombre del pool. Es posible crear múltiples agrupaciones por archivo. Cada grupo debe comenzar con esta directiva.
listen: interfaz para escuchar peticiones. Las sintaxis aceptadas son ADDRESS_IP: PORT (ejemplo: listen = 127.0.0.1.19000) y / path / to / unix / socket (ejemplo: listen = /var/run/koken.sock).
listen.owner & listen.group: Asigne el usuario y el grupo al socket Unix si se usa. Estos dos parámetros se pueden asociar con el parámetro listen.mode que establece los permisos de socket (660 de forma predeterminada). Es importante que Nginx tenga derechos de lectura en el socket Unix.
user y group: El usuario y el grupo bajo los cuales se ejecutará el grupo de procesos. Por supuesto, este usuario y este grupo deben existir en su sistema y, especialmente, acceder a los archivos PHP de su Koken. También significa que cada archivo y directorio creado en Koken pertenecerá a ese usuario y grupo. Cada archivo debe pertenecer al usuario koken y al grupo www-data.
pm: Directiva que acepta los siguientes 3 valores: static, dynamic y ondemand.
* estático: Los procesos, como pm.max_children, están continuamente activos (independientemente de la carga y la afluencia de su Koken) y es probable que consuman memoria innecesariamente. Se recomienda esta directiva si Koken es la única aplicación de su servidor.
* dinámico: El número de procesos secundarios puede variar según la carga. Sin embargo, mantenemos el control sobre la cantidad de procesos secundarios que se crearán en el inicio del servidor, la cantidad máxima de procesos, las solicitudes pendientes, etc. Las siguientes directivas pasan a ser obligatorias: pm.max_children, pm.start_servers, pm.min_spare_servers, pm.max_spare_servers. Se recomienda esta directiva si tiene varios grupos con alto tráfico (más de 10,000 solicitudes / día).
*ondemand: No se inicia ningún proceso secundario al iniciar el servidor, los procesos se activan a pedido y tendrán una vida útil definida por la directiva pm.process_idle_timeout. El interés de esta directiva es liberar memoria en caso de poca carga, pero puede aumentar ligeramente el tiempo de respuesta de su Koken. Sabiendo que el uso de Koken es personal y, a menudo, limitado a unos pocos usuarios, elegiremos y detallaremos aquí la directiva ondemand.
pm.max_children: Número máximo de procesos secundarios. El valor del parámetro pm.max_children varía de un sistema a otro. Aquí está el procedimiento a realizar para determinar el valor de este parámetro:
root@gallery:~# sudo systemctl stop php7.3-fpm.service root@gallery:~# free -m total used free shared buff/cache available Mem: 2048 83 1873 139 91 1964 Swap: 6144 0 6144
En este ejemplo, el sistema tiene 1873 MB de RAM disponible. La cantidad de RAM que desea asignar a Koken tanto como sea posible depende de usted y de los otros servicios activos que tenga en el mismo sistema. En nuestro ejemplo, asumiremos que queremos asignar hasta 1024 MB de RAM a Koken.
Ver la memoria utilizada por un proceso hijo php-fpm:
root@gallery:~# systemctl start php7.3-fpm.service && ps --no-headers -o "rss,cmd" -C php-fpm7.3 | awk '{ sum+=$1 } END { printf ("%d%sn", sum/NR/1024,"M") }' 17M
Determine el número de pm.max_children aplicando el siguiente método de cálculo:
pm.max_children = memoria asignada (en MB) / memoria utilizada por un proceso hijo
En nuestro ejemplo: 1024/17 = 60
NOTA: Ustedes pondrán el valor que es haya dado su cálculo o pueden utilizar el mío.
pm.process_idle_timeout: La cantidad de tiempo en segundos antes de que se destruya un proceso hijo inactivo.
pm.max_requests: La cantidad de consultas que cada proceso hijo deberá ejecutar antes de ser destruido. Este valor no debe ser demasiado alto para evitar cualquier pérdida de memoria, ni demasiado bajo para no solicitar regularmente la CPU para cada creación de proceso hijo. 500 sigue siendo un valor recomendado.
env [*]: Variables de entorno necesarias para PHP-FPM.
systemctl restart php7.3-fpm.service
5.2- Configuración del servicio PHP-FPM
Finalmente, es necesario especificar a PHP-FPM los permisos de cada archivo o directorio creado recientemente en su Koken.
systemctl edit php7.3-fpm.service _______________________________________________________ poner esto [Service] UMask=0027
Reactivamos el servicio
root@gallery:~# systemctl reenable php7.3-fpm.service Removed /etc/systemd/system/multi-user.target.wants/php7.3-fpm.service. Created symlink /etc/systemd/system/multi-user.target.wants/php7.3-fpm.service -> /lib/systemd/system/php7.3-fpm.service.
6- Instalando MariaDB y creando la base de datos de Koken
apt install mariadb-server
6.1- Configuracion de MariaDB
root@gallery:~# mysql_secure_installation NOTE: RUNNING ALL PARTS OF THIS SCRIPT IS RECOMMENDED FOR ALL MariaDB SERVERS IN PRODUCTION USE! PLEASE READ EACH STEP CAREFULLY! In order to log into MariaDB to secure it, we'll need the current password for the root user. If you've just installed MariaDB, and you haven't set the root password yet, the password will be blank, so you should just press enter here. Enter current password for root (enter for none): OK, successfully used password, moving on... Setting the root password ensures that nobody can log into the MariaDB root user without the proper authorisation. Set root password? [Y/n] y New password: Re-enter new password: Password updated successfully! Reloading privilege tables.. ... Success! By default, a MariaDB installation has an anonymous user, allowing anyone to log into MariaDB without having to have a user account created for them. This is intended only for testing, and to make the installation go a bit smoother. You should remove them before moving into a production environment. Remove anonymous users? [Y/n] y ... Success! Normally, root should only be allowed to connect from 'localhost'. This ensures that someone cannot guess at the root password from the network. Disallow root login remotely? [Y/n] y ... Success! By default, MariaDB comes with a database named 'test' that anyone can access. This is also intended only for testing, and should be removed before moving into a production environment. Remove test database and access to it? [Y/n] y - Dropping test database... ... Success! - Removing privileges on test database... ... Success! Reloading the privilege tables will ensure that all changes made so far will take effect immediately. Reload privilege tables now? [Y/n] y ... Success! Cleaning up... All done! If you've completed all of the above steps, your MariaDB installation should now be secure. Thanks for using MariaDB! root@gallery:~#
6.2- Creacion de la base de datos Koken
root@gallery:~# mysql -u root -p Enter password: Welcome to the MariaDB monitor. Commands end with ; or \g. Your MariaDB connection id is 10 Server version: 10.1.26-MariaDB-0+deb9u1 Debian 9.6 Copyright (c) 2000, 2017, Oracle, MariaDB Corporation Ab and others. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. MariaDB [(none)]> CREATE DATABASE koken; Query OK, 1 row affected (0.00 sec) MariaDB [(none)]> CREATE USER "koken"@"localhost"; Query OK, 0 rows affected (0.00 sec) MariaDB [(none)]> SET password FOR "koken"@"localhost" = password('tu_clave'); Query OK, 0 rows affected (0.00 sec) MariaDB [(none)]> GRANT ALL PRIVILEGES ON koken.* TO "koken"@"localhost" IDENTIFIED BY "tu_clave"; Query OK, 0 rows affected (0.00 sec) MariaDB [(none)]> FLUSH PRIVILEGES; Query OK, 0 rows affected (0.00 sec) MariaDB [(none)]> EXIT Bye root@gallery:~#
7- Nombre de dominio y host virtual
Cree el siguiente archivo /etc/nginx/sites-available/koken y modifique las líneas que resalto de acuerdo con su configuración:
nano /etc/nginx/sites-available/koken ________________________________________________________________________ upstream koken { server unix:/var/run/koken.sock; } server { listen 80; listen [::]:80; server_name koken.mydomain.cu; ------------------> poner el nombre de tu server root /var/www/koken; index index.php index.html index.htm; # Enable gzip. Highly recommending for best peformance gzip on; gzip_comp_level 6; gzip_types text/css text/javascript application/json application/javascript application/x-javascript; # By default, do not set expire headers expires 0; # Set expires header for console CSS and JS. # These files are timestamped with each new release, so it is safe to cache them agressively. location ~ "console_.*.(js|css)$" { expires max; } # Catch image requests and pass them back to PHP if a cache does not yet exist location ~ "^/storage/cache/images(/(([0-9]{3}/[0-9]{3})|custom)/.*)$" { # Cached images have timestamps in the URL, so it is safe to set # aggresive cache headers here. expires max; try_files $uri /i.php?path=$1; } # Catch .css.lens requests and serve cache when possible location ~ "(lightbox-)?settings.css.lens$" { default_type text/css; try_files /storage/cache/site/${uri} /app/site/site.php?url=/$1settings.css.lens; } # Catch koken.js requests and serve cache when possible location ~ koken.js$ { default_type text/javascript; try_files /storage/cache/site/${uri} /app/site/site.php?url=/koken.js; } # Standard site requests are cached with .html extensions set $cache_ext 'html'; # PJAX requests contain the _pjax GET parameter and are cached with .phtml extensions if ($arg__pjax) { set $cache_ext 'phtml'; } if ($request_method != 'GET') { set $cache_ext 'nocache'; } # If share_to_tumblr cookie is preset, disable caching (long story) if ($http_cookie ~* "share_to_tumblr" ) { set $cache_ext 'nocache'; } # Prevent web requests to Koken's .cache files location ~ .cache$ { deny all; } # All other requests get passed back to Koken unless file already exists location / { try_files $uri $uri/ /storage/cache/site/${uri} /storage/cache/site/${uri}cache.$cache_ext /app/site/site.php?url=$uri&$args; } # Catch albums requests and pass them back to PHP if a cache does not yet exist location ~ "^/storage/cache/albums(/([0-9]{3}/[0-9]{3})/.*)$" { # Cached albums have timestamps in the URL, so it is safe to set expires max; try_files $uri /a.php?path=$1; } # pass all other PHP requests to main backend location ~ .php$ { try_files $uri =404; fastcgi_split_path_info ^(.+.php)(/.+)$; fastcgi_pass koken; fastcgi_index index.php; include fastcgi.conf; } }
Si desean una configuracion que incluya SSL ya sea con Let‘s Encrypt o autogenerada se las dejo tambien:
upstream koken { server unix:/var/run/koken.sock; } server { listen 80; listen [::]:80; server_name koken.mydomain.cu; ---------------> nombre de su servidor return 301 https://$server_name$request_uri; } server { listen 443 ssl; listen [::]:443; server_name koken.mydomain.cu; ---------------> nombre de su servidor root /var/www/koken; index index.php index.html index.htm; ssl on; ----->bloque de SSL ssl_certificate /etc/letsencrypt/live/koken.mydomain.cu/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/koken.mydomain.cu/privkey.pem; ssl_trusted_certificate /etc/letsencrypt/live/koken.mydomain.cu/chain.pem; ssl_dhparam /etc/ssl/certs/dhparam.pem; ssl_session_cache shared:SSL:1m; ssl_session_timeout 1440m; ssl_buffer_size 8k; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers 'kEECDH+ECDSA+AES128 kEECDH+ECDSA+AES256 kEECDH+AES128 kEECDH+AES256 kEDH+AES128 kEDH+AES256 DES-CBC3-SHA +SHA !aNULL !eNULL !LOW !kECDH !DSS !MD5 !EXP !PSK !SRP !CAMELLIA !SEED'; ssl_prefer_server_ciphers on; ssl_ecdh_curve secp384r1; ssl_stapling on; ssl_stapling_verify on; add_header Strict-Transport-Security "max-age=63072000"; # Enable gzip. Highly recommending for best peformance gzip on; gzip_comp_level 6; gzip_types text/css text/javascript application/json application/javascript application/x-javascript; # By default, do not set expire headers expires 0; # Set expires header for console CSS and JS. # These files are timestamped with each new release, so it is safe to cache them agressively. location ~ "console_.*.(js|css)$" { expires max; } # Catch image requests and pass them back to PHP if a cache does not yet exist location ~ "^/storage/cache/images(/(([0-9]{3}/[0-9]{3})|custom)/.*)$" { # Cached images have timestamps in the URL, so it is safe to set # aggresive cache headers here. expires max; try_files $uri /i.php?path=$1; } # Catch .css.lens requests and serve cache when possible location ~ "(lightbox-)?settings.css.lens$" { default_type text/css; try_files /storage/cache/site/${uri} /app/site/site.php?url=/$1settings.css.lens; } # Catch koken.js requests and serve cache when possible location ~ koken.js$ { default_type text/javascript; try_files /storage/cache/site/${uri} /app/site/site.php?url=/koken.js; } # Standard site requests are cached with .html extensions set $cache_ext 'html'; # PJAX requests contain the _pjax GET parameter and are cached with .phtml extensions if ($arg__pjax) { set $cache_ext 'phtml'; } if ($request_method != 'GET') { set $cache_ext 'nocache'; } # If share_to_tumblr cookie is preset, disable caching (long story) if ($http_cookie ~* "share_to_tumblr" ) { set $cache_ext 'nocache'; } # Prevent web requests to Koken's .cache files location ~ .cache$ { deny all; } # All other requests get passed back to Koken unless file already exists location / { try_files $uri $uri/ /storage/cache/site/${uri} /storage/cache/site/${uri}cache.$cache_ext /app/site/site.php?url=$uri&$args; } # Catch albums requests and pass them back to PHP if a cache does not yet exist location ~ "^/storage/cache/albums(/([0-9]{3}/[0-9]{3})/.*)$" { # Cached albums have timestamps in the URL, so it is safe to set expires max; try_files $uri /a.php?path=$1; } # pass all other PHP requests to main backend location ~ .php$ { try_files $uri =404; fastcgi_split_path_info ^(.+.php)(/.+)$; fastcgi_pass koken; fastcgi_index index.php; include fastcgi.conf; fastcgi_param HTTPS on; } }
Creamos el enlace simbolico y reiniciamos el servicio
ln -s /etc/nginx/sites-available/koken /etc/nginx/sites-enabled/koken systemctl restart nginx.service systemctl restart php7.3-fpm.service
8- Mejora el rendimiento de tu Koken con OPcache
OPcache (que significa Optimizer Plus Cache) se utiliza para ocultar el código de operación de PHP, que son las instrucciones de bajo nivel generadas por la máquina virtual de PHP cuando se ejecuta un script. En otras palabras, el código precompilado se almacena en la memoria. Esto evita el paso de compilación para cada solicitud de PHP. Además, OPcache optimizará la ejecución del código para mejorar el rendimiento.
nano /etc/php/7.3/fpm/php.ini _______________________________________________________ [opcache] opcache.enable=1 opcache.enable_cli=1 opcache.memory_consumption=128 opcache.interned_strings_buffer=8 opcache.max_accelerated_files=10000 opcache.validate_timestamps=1 opcache.revalidate_freq=1 opcache.save_comments=1
9- KOKEN
Inicie su navegador y vaya a la siguiente dirección: http://koken.mydomain.cu/. Donde koken es el nombre que le dimos al servidor y que definimos anteriormente.
Luego de instalado, para administrarlo usando el usuario que definimos anteriormente usaremos este link http://koken.mydomain.cu/admin . Donde koken es el nombre que le dimos al servidor y que definimos anteriormente.
10- Instalacion detras de un proxy.
Como pueden observar el archivo Koken previamente descargado y sin comprimir en la carpeta /var/www/koken contiene un solo archivo index.php. Este archivo es un script de instalación de PHP que, cuando se ejecuta en su navegador, descargará automáticamente la última versión de los archivos necesarios para ejecutar Koken y creará los archivos de configuración necesarios para conectarse a su base de datos koken. Los que estén directo a internet no tendrán ningún problema en su instalación pero los que estén detrás de un proxy padre no alcanzaran instalar. Por lo que me di a la tarea de investigar el script en sí y aportar mi solución a este problema y se los regalo a todos. Editamos el index.php que descompactamos de Koken_Installer .zip
nano /var/www/koken/index.php
Agregamos las lineas sugeridas en el bloque ubicado desde la linea 133 a la 159.
function download($f, $to, $test = false) { $error = false; if (in_array('curl', get_loaded_extensions())) { $cp = curl_init($f); $fp = fopen($to, "w+"); $proxy = 'proxy.domain.cu:port' --------->variable con el proxy if (!$fp) { curl_close($cp); $error = 'perms'; } else { curl_setopt($cp, CURLOPT_FILE, $fp); curl_setopt($cp, CURLOPT_PROXY, $proxy); ----------> php-curl usando proxy curl_setopt($cp, CURLOPT_CONNECTTIMEOUT, 10); curl_setopt($cp, CURLOPT_FOLLOWLOCATION, true); curl_setopt($cp, CURLOPT_SSL_VERIFYPEER, false); if (curl_exec($cp) === false) { fclose($fp); @unlink($to); $error = curl_error($cp); } else { fclose($fp); } curl_close($cp); }
Finalmente, después de instalada solo nos queda crear nuestros albúmenes y disfrutar de esta librería profesional de fotos.
alex out
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36
$proxy = ‘proxy.domain.cu:port’— debe de haber un ; al final para los usuarios que están bajo proxy
$proxy = ‘proxy.domain.cu:port’; Así