Proxmox: habilitar virtualización anidada (nesting virtualization)

Uno de los problemas que me estoy encontrando últimamente es que los contenedores lxc que instalo con debian 10 no arrancan los servicios porque tengo que reconfigurar systemd para decirle que el PrivateTmp es false, por ejemplo para poder levantar apache2 tendría que hacer ésto

Job for apache2.service failed because the control process exited with error code.
See "systemctl status apache2.service" and "journalctl -xe" for details.
invoke-rc.d: initscript apache2, action "start" failed.
* apache2.service - The Apache HTTP Server
   Loaded: loaded (/lib/systemd/system/apache2.service; enabled; vendor preset: enabled)
   Active: failed (Result: exit-code) since Wed 2020-07-01 16:35:29 UTC; 9ms ago
     Docs: https://httpd.apache.org/docs/2.4/
  Process: 11730 ExecStart=/usr/sbin/apachectl start (code=exited, status=226/NAMESPACE)

Jul 01 16:35:29 wordpress systemd[1]: Starting The Apache HTTP Server...
Jul 01 16:35:29 wordpress systemd[11730]: apache2.service: Failed to set up mount namespacing: Permission denied
Jul 01 16:35:29 wordpress systemd[11730]: apache2.service: Failed at step NAMESPACE spawning /usr/sbin/apachectl: Permission denied
Jul 01 16:35:29 wordpress systemd[1]: apache2.service: Control process exited, code=exited, status=226/NAMESPACE
Jul 01 16:35:29 wordpress systemd[1]: apache2.service: Failed with result 'exit-code'.
Jul 01 16:35:29 wordpress systemd[1]: Failed to start The Apache HTTP Server.

# vi /lib/systemd/system/apache2.service
PrivateTmp=false
:wq
# systemctl daemon-reload
# systemctl start apache2.service

Pero me encuentro el mismo problema con otros servicios que instalo.

Por lo que entiendo systemd crea como una especie de “entorno virtual” para cada uno de los servicios y para que funcione correctamente, leyendo documentación veo que la solución es habilitar la virtualización anidada.

Así que en la documentación de proxmox encontramos ésta página que nos dice como hacerlo.

Tendremos …

Instalar entorno de producción de python

Una vez hemos desarrollado una aplicación con django nos interesará ponerla en producción. La forma correcta de hacerlo es usando uwsgi + nginx. Así que vamos a ello.

Mi aplicación corre sobre postgresql así que instalaremos los siguientes paquetes

# apt -y install nginx uwsgi uwsgi-plugin-python3 postgresql python3-psycopg2 libpq-dev git virtualenv memcached

Creamos el usuario y la base de datos postgresql

# su - postgres
$ createuser colibri_user
$ createdb -O colibri_user colibri_db
$ psql colibri_db
colibri_db=# alter user colibri_user with encrypted password 'XXXXXXXX';
colibri_db=# grant all privileges on database colibri_db to colibri_user;

Ahora clonamos el código del programa en /var/www

# cd /var/www/
# git clone git@git.capa8.net:blackhold/colibri.git

Creo el entorno virtual

# cd colibri
# virtualenv -p python3 venv

Entro en el entorno virtual y ejecuto los comandos necesarios para iniciar la aplicación

# source venv/bin/activate
# pip install -r requirements.txt
# ./clean.sh
# python manage.py runserver 0.0.0.0:5001

Ahora configuramos uwsgi para que apunte donde está nuestra aplicación de django

# cd /etc/uwsgi/apps-available
# vi colibri.ini
[uwsgi]
master = true
processes = 10
socket = /tmp/uwsgi-colibri.sock
uid = www-data
gid = www-data

;# with appropriate permissions - *may* be needed
;chmod-socket    = 664

chdir = /var/www/colibri
module = colibri.wsgi
home = /var/www/colibri/venv/
vacuum = true
env = DJANGO_SETTINGS_MODULE=colibri.settings
safe-pidfile = /tmp/uwsgi-colibri.pid
;harakiri = 20 # respawn processes taking more than 20 seconds
;limit-as = 128 # limit the project to 128 MB
max-requests = 5000
daemonize = /var/log/uwsgi/colibri.log
;callable = application
plugin = python37

Guardamos y lo activamos en …

Proxy nginx: Redirigir las IPs reales

Me encuentro con una aplicación la cual tengo detrás de un frontal de nginx. La cuestión es que la petición al servidor llega con la IP interna del frontal de nginx en lugar de la IP real del cliente.

Para ello tendremos que realizar una configuración en el frontal de nginx para pasar la IP real del usuario y otra en el nginx de la aplicación para que interprete correctamente la IP.

Frontal nginx

root@frontal1-nginx:~# vi /etc/nginx/sites-enabled/app.capa8.net
server {
    listen 80;

    server_name app.capa8.net;
    return 301 https://app.capa8.net$request_uri;
    #root /var/www/html/;
}

server {
        server_name app.capa8.net;

        listen 443 ssl;
        ssl_certificate /etc/letsencrypt/live/app.capa8.net/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/app.capa8.net/privkey.pem;
        include /etc/letsencrypt/options-ssl-nginx.conf;
        ssl_trusted_certificate /etc/letsencrypt/live/app.capa8.net/chain.pem;

        location / {
                proxy_set_header  Host $host;
                proxy_set_header  X-Real-IP $remote_addr;
                proxy_set_header  X-Forwarded-Proto https;
                proxy_set_header  X-Forwarded-For $remote_addr;
                proxy_set_header  X-Forwarded-Host $remote_addr;
                proxy_pass http://192.168.100.15:80;
        }
}

nginx Aplicación

Siendo set_real_ip_from la subred por donde pueden venir las peticiones de proxy

root@app:~# vi /etc/nginx/sites-enabled/app
server {
    listen 80;
    server_name app.capa8.net;

    set_real_ip_from 192.168.100.0/24;
    real_ip_header X-Real-IP;
    real_ip_recursive on;

    location / {
        include uwsgi_params;
        uwsgi_pass unix:/tmp/uwsgi-app.sock;
    }

    # /static
    location /static/ {
        autoindex off;
        root /var/www/app/web/;
    }

    location /static/admin {
        autoindex off;
        root /var/www/app/venv/lib/python3.5/site-packages/django/contrib/admin/;
    }
}

Reiniciamos ambos nginx y comprobamos en los logs que la ip pasa correctamente.

Fuente: Forward IP Addresses with NGINX Proxy

Redirección de puertos con iptables + contrack

Pues seguimos con éstos pequeños errores que hemos cometido siempre y que ahora en un momento de cambios y con mucho mas entendimiento llegan mejores soluciones para que las cosas funcionen mejor (tanto a nivel técnico como personal). Hoy estoy tiernecilla y quiero agradecer con éste post todas éstas personas que seguís los posts que publico y tenéis al igual que yo éste blog como una herramienta de consulta, un lugar claro, sin muchas complicaciones donde encontrar justo aquello que necesito en cada momento o me da la pista para poder seguir avanzando con algo mas grande que estoy construyendo con el paso de los días.

Ésta vez me encuentro solucionando un problema que inicialmente parecía de nginx pero ha resultado ser de iptables, y es que las cosas nunca son lo que parecen a primera vista y es necesario tener un gran conocimiento del sistema para entender como poder solucionar los problemas de base y encontrar una solución definitiva que evita fallos futuros, para casos como hoy que ya en producción me encuentro con un problema grave de base. Para que un sistema funcione bien, las capas inferiores (base) deben estar bien.

Me dejo ya de palabrerías y comentarios dobles y me pongo en materia. El post que rectifico es éste: Proxmox + nat + iptables.

Gracias a las configuraciones de las antenas en los supernodos entiendo que se deben marcar los paquetes tanto de entrada (prerouting) como de salida (postrouting). En TCP hay una llamada de un …

Debian 10: Problema al hacer dpkg -i paquete.deb

Acabo de instalar mi primera debian con entorno gráfico con cinnamon y veo que le faltan bastantes cosillas

# apt -y install mate-terminal pluma glances mtr net-tools dnsutils

Y también que al hacer dpkg -i de algun paquete me suelta éste error:

# dpkg -i google-chrome-stable_current_amd64.deb 
dpkg: avís: no s'ha trobat «ldconfig» en el PATH o no és executable
dpkg: avís: no s'ha trobat «start-stop-daemon» en el PATH o no és executable
dpkg: s'ha produït un error: no s'han trobat 2 programes esperats al PATH, o no són executables
Nota: el PATH del root normalment ha de contenir /usr/local/sbin, /usr/sbin i /sbin

El motivo es que necesitamos definir los directorios donde se encuentran los binarios del sistema:

# echo 'export PATH=$PATH:/usr/local/sbin:/usr/sbin:/sbin' /home/aspertic/.bashrc
# echo 'export PATH=$PATH:/usr/local/sbin:/usr/sbin:/sbin' /root/.bashrc

Salimos de la sesión de terminal del usuario y la volvemos a iniciar y ta-dá!

Recuerdo que si un paquete no deja instalar las dependencias, tenemos que forzar la instalación manual con apt -f install

root@aspertic01:/home/aspertic/Baixades# dpkg -i teamviewer_14.5.1691_amd64.deb 
S'està seleccionant el paquet teamviewer prèviament no seleccionat.
(S'està llegint la base de dades… hi ha 173445 fitxers i directoris instal·lats actualment.)
S'està preparant per a desempaquetar teamviewer_14.5.1691_amd64.deb…
S'està desempaquetant teamviewer (14.5.1691)…
dpkg: problemes de dependències impedeixen la configuració de teamviewer:
 teamviewer depèn de libqt5gui5 (= 5.5) | qt56-teamviewer; tot i així:
  El paquet libqt5gui5 no està instal·lat.
  El paquet qt56-teamviewer no està instal·lat.

 [...]

dpkg: s'ha produït un error en processar el paquet teamviewer (--install):
 problemes de dependències - es deixa sense 

Ejemplo script de backup

Aquí os dejo uno de los scripts de backup que uso para hacer la copia de seguridad de los servidores con proxmox. Espero que os sea de ayuda :)

#!/bin/bash

## lmdb-backup (proxmox)
#### Loc: ******
#### OS: Debian 9 (container lxc)
#### Up: 2019/08/28 11:45 (Blackhold)

BACKUP_DIR="/mnt/hd_extern/backups_lmdb"
ID[0]="server1:x.x.x.x1"
ID[1]="server2:x.x.x.x2"

for INFO in "${ID[@]}"
do
    HOST=`echo ${INFO} |awk -F ':' '{print $1}'`
    IP=`echo ${INFO} |awk -F ':' '{print $2}'`
    BACKUP_DIR_SERVER="${BACKUP_DIR}/${HOST}"

    if [[ ! -e ${BACKUP_DIR_SERVER} ]]; then
        mkdir ${BACKUP_DIR_SERVER}
        mkdir ${BACKUP_DIR_SERVER}/daily
        mkdir ${BACKUP_DIR_SERVER}/monday
        mkdir ${BACKUP_DIR_SERVER}/15
        mkdir ${BACKUP_DIR_SERVER}/28
        mkdir ${BACKUP_DIR_SERVER}/lastmonth
    fi

    rsync -av --delete root@${IP}:/var/lib/vz2/dump/ ${BACKUP_DIR}/${HOST}/daily/dump/
    rsync -av --delete root@${IP}:/var/lib/vz2/template/ ${BACKUP_DIR}/${HOST}/daily/template/

    if [[ $(date +%e) -eq 28 ]]; then
        echo Backup final de mes
        rsync -av --delete ${BACKUP_DIR}/${HOST}/28/dump/ ${BACKUP_DIR}/${HOST}/lastmonth/dump/
        rsync -av --delete ${BACKUP_DIR}/${HOST}/28/template/ ${BACKUP_DIR}/${HOST}/lasthmonth/template/

        rsync -av --delete ${BACKUP_DIR}/${HOST}/daily/dump/ ${BACKUP_DIR}/${HOST}/28/dump/
        rsync -av --delete ${BACKUP_DIR}/${HOST}/daily/template/ ${BACKUP_DIR}/${HOST}/28/template/
    fi

    if [[ $(date +%e) -eq 15 ]]; then
        echo Backup dia 15
        rsync -av --delete ${BACKUP_DIR}/${HOST}/daily/dump/ ${BACKUP_DIR}/${HOST}/15/dump/
        rsync -av --delete ${BACKUP_DIR}/${HOST}/daily/template/ ${BACKUP_DIR}/${HOST}/15/template/
    fi

    if [[ $(date +%u) -eq 1 ]]; then
        echo Backup dilluns
        rsync -av --delete ${BACKUP_DIR}/${HOST}/daily/dump/ ${BACKUP_DIR}/${HOST}/monday/dump/
        rsync -av --delete ${BACKUP_DIR}/${HOST}/daily/template/ ${BACKUP_DIR}/${HOST}/monday/template/
    fi
done

Y lo añado en cron

root@lmdb-backup:~# vi /etc/cron.d/lmdb
# backup planets - activated on 2019-08-18 - blackhold
30 1    * * *   root    /root/scripts/backup_nodes_planet_lmdb.sh

Por supuesto, para hacer funcionar el script es necesario instalar rsync y también poner la clave pública del servidor de backups en el autorized_keys (ssh) de los servidores que queramos hacer copia de seguridad. Recomiendo fervientemente que ninguno de los servidores ni contenedores, tenga acceso directo …

GlusterFS

GlusterFS es un gestor de ficheros en red. Básicamente lo que permite es replicar unos mismos ficheros en varios servidores, para luego con los clientes de glusterfs conectar a alguno de ellos y definir otro de backup en el caso de que se caiga el primero. Con éste sistema tenemos redundancia de los datos.

La recomendación es usar 3 nodos servidores de gluster, en mi caso, ahora mismo no dispongo del tercero, y lo añadiré mas tarde.

Vamos a trabajar con 3 nodos, Node1A, Node1B y Node2A, los dos primeros serán los servidores que tendrán el disco duro que queremos compartir en red, y el último sólo va a actuar como cliente.…

proxmox 6 + ceph

Por fin otro logro mas que me había dado guerra durante muchas horas, el motivo un ceph roto al que de momento he preferido migrar los datos a otro sitio y ya con mas calma intentaremos recuperarlo (ya vendrá otro post otro día sobre éste tema).

En motivo del ceph roto he aprovechado para reinstalar la infraestructura de proxmox entera sobre proxmox6 (debian10).

Partimos de 5 nodos unidos en el cluster (pvecm add ipmaster), sólo vamos a instalar ceph en 3 de ellos.

- node1A - 172.31.0.1 (ceph)
- node1B - 172.31.0.2
- node1C - 172.31.0.3 (ceph)
- node1D - 172.31.0.4 (ceph)
- node2D - 172.31.0.8

El nodo maestro del cluster es “node1D”, y para ver que ésto no implica nada a la hora de configurar ceph y también porque romper el 1D era una cosa que no me podía permitir… vamos a empezar por “node1A”.

Para ello vamos a la interfaz web de proxmox e instalamos ceph:…

Levantar tunnel vtun con lxc (proxmox)

Me encuentro con éste error

Oct 31 13:16:06 asterisk vtund[1748]: VTun client ver 3.X 05/15/2013 started
Oct 31 13:16:06 asterisk vtund[1748]: Connecting to 213.162.195.57
Oct 31 13:16:06 asterisk vtund[1748]: Use SSL-aware challenge/response
Oct 31 13:16:06 asterisk vtund[1748]: Remote Server sends #012.
Oct 31 13:16:06 asterisk vtund[1748]: Session sipcapa8[213.162.195.57] opened
Oct 31 13:16:06 asterisk vtund[1748]: Can't allocate tun device tun1000. No such file or directory(2)
Oct 31 13:16:06 asterisk vtund[1748]: Session sipcapa8[x.x.x.x] closed
Oct 31 13:16:06 asterisk vtund[1748]: Exit
Oct 31 13:17:09 asterisk vtund[1727]: Terminated

El motivo es que al tratar de levantar interfaces de red dentro del lxc no tenemos permisos y tenemos que definirle que éste contenedor si puede levantar interfaces de red.

Primero entramos en el host donde se encuentra el contenedor y apagamos el contenedor

# pct shutdown 104

Para ello modificamos el fichero de configuración del contenedor y añadimos al final ésta línea

root@wezen-04:/etc/pve/lxc# vi /etc/pve/lxc/104.conf
lxc.cgroup.devices.allow: c 10:200 rwm

Ahora arrancamos el contenedor de nuevo y ejecutamos los siguientes comandos

root@wezen-04:/etc/pve/lxc# pct start 104
root@wezen-04:/etc/pve/lxc# pct enter 104
root@asterisk:/# mkdir /dev/net
root@asterisk:/# mknod /dev/net/tun c 10 200
root@asterisk:/# ip tuntap add mode tap
root@asterisk:/# ip link
root@asterisk:/# service vtun restart
root@asterisk:/# ifconfig |grep tun
tun0      Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00   
tun1000   Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-0

Los comandos que hemos puesto los tendremos que ejecutar cada vez que reiniciemos la máquina, así que le decimos que ejecute éstos comandos justo después de levantar la interfaz de red

auto eth1
iface eth1 inet static
        address x.x.x.x
        netmask 255.255.255.224
        

Modoboa: mi solución a mis problemas de mail

Vale, el post de antes… si os queréis complicar la vida… ya lo arreglaré, pero de momento traigo otra solución… en menos de un par de horas ya tengo un servidor de correo multi-dominio que se monta plis-plas… se llama modoboa y tiene todo lo que busco :)

Partimos de una debian9 con IP pública y los DNS apuntando a mail.nusepas.com.

Ahora descargaremos el instalador de modoboa y lo ejecutaremos

root@mail-nusepas:~# cd /usr/src
root@mail-nusepas:/usr/src# git clone https://github.com/modoboa/modoboa-installer
root@mail-nusepas:/usr/src# cd modoboa-installer/
./run.py nusepas.com

La instalación durará unos 20 minutos aproximadamente. Una vez pasados, haces login en https://mail.nusepas.com y entras con el usuario y contraseña por defecto que nos indica al final de la instalación.…