Archivo de la etiqueta: manual

Como hacer una copia de seguridad completa de nuestro servidor, base de datos y WordPress

Los backups son necesarios para cualquier sistema para prevenir la pérdida de datos. Siguiendo un poquito con la tónica de los últimos posts, instalar wordpress en un servidor propio y usar certificados SSL para nuestro WordPress, esta vez lo que haremos será un backup completo de nuestro WordPress. En este post lo que hago es crear un cronjob, osease un script que se ejecute a diario y haga una copia completa de nuestra base de datos juntamente con distintas carpetas que queramos conservar de nuestro blog.

Generamos un dump de todas las bases de datos

La base de datos es uno de los componentes más importantes de cualquier sistema. Es donde históricamente se ha guardado la información. Para hacer una copia de la base de datos necesitaremos mysqldump. Esto nos permitirá sacar una copia consistente de la base de datos.  Para obtener la copia de todas las bases de datos ejecutaremos el comando

mysqldump -u[usuario] -p[contraseña] --single-transaction --quick --all-databases > output.sql

El fichero output.sql contendrá toda la información en la base de datos.

Agruparemos todos los directorios y documentos en un solo archivo

Una vez ya tengamos generado el dump de nuestra base de datos lo que tendremos que hacer es crear un archivo único para mejorar la transportabilidad del backup. En mi caso también lo comprimo usando gzip para ahorrar espacio, ya que raramente se consultan/usan los backups y así ahorro espacio. En mi caso he usado tar (para una introducción podéis leer mi anterior post a tar) para mantener los permisos de cada archivo.

tar cfz /home/donde/quieras/archivo.tar.gz /var/www/ /directorio/hacia/backup/output.sql

En el comando anterior vemos que hemos creado un archivo comprimido que contiene el directorio var/www, y el dump que hemos hecho de la base de datos /directorio/hacia/backup/output.sql

Subiremos el archivo comprimido a un servidor externo

Para asegurarnos que cualquier problema que pueda tener nuestra máquina no afecte a nuestros backups subiremos el archivo comprimido a un servidor externo. Imagínate que haces sólo los backups pero los dejas en tu ordenador y el disco duro se estropea. Si pasa eso no podrías recuperar la información. Por esto es importante guardar copias de seguridad en distintos sitios.

Para este apartado he creado como un mini-script con las instrucciones para que el cliente FTP lo ejecute y haga la copia. En mi caso lo voy a guardar con el nombre ftp.txt

open [url o IP]
user usuario contraseña
passive #algunas veces requerido
put /home/donde/tenías_el/archivo.tar.gz nombre_del_archvo_en_el_ftp.tar.gz
bye

Finalmente ejecutaremos este trozo de código con

 ftp -n < ftp.txt

Asignaremos un cronjob que haga backups y los salvaguarde

A partir de la segunda vez que tienes que realizar una tarea uno tiene que empezar a pensar de que modo puede optimizar el proceso. Lo que he decidido hacer es crear un cronjob para que haga una copia de seguridad a diario y la suba al servidor externo mediante FTP.

echo "Starting script: $(date)"
day=$(date +"%d")

echo "Doing the mysql dump of all tables"
mysqldump -u[usuario] -p[contraseña] --single-transaction --quick --all-databases > output.sql

echo "Compressing the websites and the mysql dump into one file"
tar cfz /home/donde/quieras/archivo.tar.gz /var/www/ /directorio/hacia/backup/output.sql

echo "open url o IP 
user usuario contraseña 
passive #algunas veces requerido 
put /home/donde/tenías_el/archivo.tar.gz nombre_del_archvo_en_el_ftp.tar.gz 
bye" > ftp.txt

echo "Executing FTP and uploading the file"
ftp -n < ftp.txt

rm ftp.txt

Este vendría a ser el script que va a ejecutar el cronjob. Pero para ejecutar el script de forma automática tendremos que guardarlo propiamente como cronjob. Para esto usaremos el siguiente comando para editar los cronjobs de nuestro sistema.

crontab -e

y dentro del fichero, al final, escribiremos el siguiente comando

00 4 * * * sh /camino/hacia/cronjobs/cron_backup.txt > /dev/null 2>&1

Este comando ejecuta el script en /camino/hacia/cronjobs/cron_backup.txt cada día (los asteriscos) a las 4:00 (am) sin guardar el output (> /dev/null 2>&1). Ahora guardaremos el fichero y ya lo tendremos inicializado.

Para aprender un poquito más sobre los cronjobs podéis leer mi entrada anterior dónde lo explico más detalladamente.

Finalmente para recuperar los archivos

Cuando lo más temido pasa, cuando se nos estropea el ordenador y tenemos que ir a buscar los backups, lo tendremos todo preparado.

Primero nos logearemos con el cliente FTP y nos descargaremos el archivo con los backups.

ftp [url o IP]

pondremos el nombre de usuario y contraseña cuando nos lo pida. Una vez logueados descargaremos el fichero con el backup en nuestro ordenador local

get Nombre_del_backup.tar.gz

Saldremos de la sesión para descomprimir y extraer los archivos

tar xf Nombre_del_backup.tar.gz

Todo lo que sea blogs WordPress tendremos que copiar los ficheros en /var/ww/ otra vez y volver a configurar el apache. En cuanto la base de datos tendremos que importar el dump

mysql -u[usuario] -p output.sql

Y de este modo ya habremos recuperado todo lo que temíamos haber perdido.

Cómo forzar WordPress para que use un certificado SSL gratis mediante un plugin

En los posts anteriores hemos instalado WordPress y hemos alojado varios sitios en un mismo servidor. En este post lo que haremos será mejorar la seguridad de nuestro blog y las SERPs en Google. Hace ya un tiempo Google recomendó a los webmasters dejar de usar http y pasar a https para hacer la web más segura. Para forzar un poco el brazo Google ofreció mejoras en los rankings a aquellas webs que usaran un certificado SSL. Como no es fácil para todos los bloggers comprar un certificado SSL lo que propongo es obtener gratuitamente un certificado de SSL gracias a cloudflare y así poder ofrecer nuestro blog de forma más segura para los usuarios.  Para conseguirlo solo tenemos que seguir los siguientes pasos.

Instalar el plugin para el certificado SSL en wordpress

Para instalar el plugin WordPress podemos ir al apartado de plugins y buscar “WordPress HTTPS” e instalarlo usando el panel de control. También podemos instalarlo manualmente mediante FTP, subiéndolo directamente a la carpeta de /wp-content/plugins/ e instalándolo como cualquier otro complemento. Una vez instalado lo activaremos.

Conseguir el certificado SSL gratis

La mayoría de certificados son de pago pero cloud cloudflare fare nos permite usar un certificado SSL gratis para proyectos más modestos. Lo único que tenemos que hacer es registrarnos y añadir la página web cuando nos la pidan. Finalmente cambiaremos los name servers en nuestro registrador de dominios.

Actualizar los ficheros de configuración de WordPress

Finalmente iremos a ajustes generales en la sección de ajustes de nuestro blog wordpress y cambiaremos http por https dejando el resto de la url intacta. Por algún motivo que desconozco he tenido que cambiar el fichero wp-config.php. Justo antes de /* That’s all, stop editing! Happy blogging. */ he tenido que añadir

define('FORCE_SSL_ADMIN', false);

para poder acceder al wp-admin.

Espero que esto os haya servido para mejorar la seguridad del blog y los rankings de las SERPs.

Instalar WordPress en un servidor propio

Como ya vimos el otro día, podemos alojar varios sitios web en un mismo servidor. En mi caso para lo que los quería era para instalar distintas instancias de WordPress (osease distintos blogs). Pero para usar WordPress requerimos distintas aplicaciones para las diferentes partes del sistema.

PHP

Primero instalaremos PHP para que los scripts de WordPress puedan ser ejecutados.

sudo apt-get install php apache2 libapache2-mod-php php-mcrypt php-mysql

Base de datos

Ahora instalaremos la base de datos

sudo apt-get install mysql-server
 sudo mysql_secure_installation
 sudo mysql_install_db

y crearemos los usuarios para cada uno de nuestro blog. Primero nos logearemos como root para poder crear usuarios

mysql -u root -p

crearemos el usuario

GRANT ALL PRIVILEGES ON *.* TO 'user'@'localhost' IDENTIFIED BY 'pass';

Saldremos de la conexión con la base de datos con el root, y nos logearemos con el nuevo usuario

 mysql -u user -p

y crearemos una nueva base de datos para el blog

CREATE DATABASE db_wordpress;

Scripts de WordPress

Nos bajaremos la última versión de WordPress. La descomprimiremos y la pondremos en /var/www/directorio-de-tu-blog/. Para terminar de configurar el apache podéis seguir esta guía.

Finalizar

Para finalizar y que los cambios tengan efecto reiniciaremos apache

sudo systemctl restart apache2
 apt-cache search php- | less

y accederemos a la url de nuestro blog. Allí se nos pedirá que ingresemos los datos de la base de datos y otra información básica sobre el blog.

Instalando tensorflow en un container de docker

Con el docker instalado podremos instalar el tensor flow en un container de docker. Ejecutaremos el siguiente comando para iniciar el container con tensor flow. La primera vez que lo ejecutemos docker se bajará todos los archivos necesarios para poder correr el container, por lo que por lo que puede tardar un poco en estar listo. A partir de la segunda vez ya tendremos todo el software requerido en el ordenador y se ejecutará sin ningún problema.

docker run -it -p 8888:8888 gcr.io/tensorflow/tensorflow

la opción -p 8888:8888 es usada para conectar el puerto interno de docker con el de la maquina física. Importante si queremos usar Jupyter notebooks. El formato es hostPort:containerPort. Y la url gcr.io/tensorflow/tensorflow contiene la imagen binaria para CPU. Hay otra con GPU, y sus respectivas con el código fuente. Aquí dejo una lista por si quieres la imagen con el codigo fuente o usar la versión GPU.

  • gcr.io/tensorflow/tensorflow: TensorFlow CPU
  • gcr.io/tensorflow/tensorflow:latest-devel: CPU y codigo fuente
  • gcr.io/tensorflow/tensorflow:latest-gpu: TensorFlow GPU
  • gcr.io/tensorflow/tensorflow:latest-devel-gpu: GPU codigo fuente

Instalando docker en Ubuntu

Esa va a a formar parte de una serie de posts. En los que voy a implementar algoritmos de inteligencia artificial en tensor flow. Y porque docker? Docker es un programa que crea virtualizaciones de sistemas operativos con un overhead muy reducido. Las virtualizaciones se llaman containers y requieren pocos recursos para poder virtualizar el entorno correctamente. La ventaja principal es que me permite crear automáticamente una instalación del sistema en cualquier ordenador sin mucho problema. La idea era actualmente hacerlo en el ordenador normal – por lo que seria innecesario usar docker – pero más adelante puede ser que use sistemas externos para realizar los trainings. Además permite separar distintas instalaciones en caso que hayas hecho modificaciones o quieras usar distintas versiones a la vez.

Primero empezaremos instalando la clave GPG oficial de docker

curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -

y añadiremos el repositorio en nuestras fuentes

sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"

Seguidamente actualizaremos la lista de paquetes disponibles para nuestra distribución

sudo apt-get update

y finalmente instalaremos docker (nótese que es docker-ce, las versiones anteriores tenian distintos nombres)

sudo apt-get install -y docker-ce

para comprobar que la instalación ha finalizado correctamente pondremos en la terminal:

sudo docker run hello-world

Que nos verificará que la instalación funciona correctamente. Cómo podéis comprobar requiere de sudo para poder usar el socket TCP para comunicarse con el sistema. Si queréis evitar esto. Tendremos que realizar unos pasos extra que pueden comprometer la seguridad del sistema.

El primer paso será crear un grupo

sudo groupadd docker

añadir el usuario al grupo

sudo usermod -aG docker $USER

para verificar que funciona y podemos evitar el uso de sudo cada vez tendremos que cerrar sesión y volver a logearnos. Una vez dentro ejecutaremos el “hello world” pero esta vez sin el sudo

docker run hello-world

Si nos sale un “permission denied” significa que algo no ha funcionado. Por el contrario si el comando se ha ejecutado correctamente se imprimirá por pantalla un mensaje algo largo incitandote a usar docker.

Optimizadores de tensor flow

Continuando el anterior post dónde introducí tensor flow hoy vengo con los optimizadores de funciones. Tensor flow ofrece optimizadores que cambian las variables para minimizar la funcion de perdida (loss function). El más simple es el de gradiente descendiente. Computan las derivadas simbólicas (symbolic derivatives) simplemente usando el modelo y la función tf.gradients. Por ejemplo:

[code language=”python”]
optimizer = tf.train.GradientDescentOptimizer(0.01)
train = optimizer.minimize(loss)
sess.run(init) # reset values to incorrect defaults.
for i in range(1000):
sess.run(train, {x:[1,2,3,4], y:[0,-1,-2,-3]})
print(sess.run([W, b]))
los resultados finales
[array([-0.9999969], dtype=float32), array([ 0.99999082],
dtype=float32)]
[/code]

El modelo completo para la regresión linal es:

[code language=”python”]
import numpy as np
import tensorflow as tf
# Model parameters
W = tf.Variable([.3], tf.float32)
b = tf.Variable([-.3], tf.float32)
# Model input and output
x = tf.placeholder(tf.float32)
linear_model = W * x + b
y = tf.placeholder(tf.float32)
# loss
loss = tf.reduce_sum(tf.square(linear_model – y)) # suma de los cuadrados
# optimizer
optimizer = tf.train.GradientDescentOptimizer(0.01)
train = optimizer.minimize(loss)
# training data
x_train = [1,2,3,4]
y_train = [0,-1,-2,-3]
# training loop
init = tf.global_variables_initializer()
sess = tf.Session()
sess.run(init) # reset values to wrong
for i in range(1000):
sess.run(train, {x:x_train, y:y_train})
# evaluate training accuracy
curr_W, curr_b, curr_loss  = sess.run([W, b, loss], {x:x_train, y:y_train})
print("W: %s b: %s loss: %s"%(curr_W, curr_b, curr_loss))
# When run, it produces
#W: [-0.9999969] b: [ 0.99999082] loss: 5.69997e-11
[/code]
tf.contrib.learn te simplifica la vida con las funciones: ejecución, entrenamiento, iteraciones, evaluaciones entre otros

[code language=”python”]
import tensorflow as tf
import numpy as np
features = [tf.contrib.layers.real_valued_column("x", dimension=1)]
estimator = tf.contrib.learn.LinearRegressor(feature_columns=features)
x = np.array([1., 2., 3., 4.])
y = np.array([0., -1., -2., -3.])
input_fn = tf.contrib.learn.io.numpy_input_fn({"x":x}, y, batch_size=4,
num_epochs=1000)
estimator.fit(input_fn=input_fn, steps=1000)
print(estimator.evaluate(input_fn=input_fn))
# Result: {‘global_step’: 1000, ‘loss’: 1.9650059e-11}
[/code]

Manual para instalar OpenVPN en Ubuntu con script

Hace ya algun tiempo me hice con un servidor y lo voy usando para hacer mis cosicas. Como por ejemplo instalar rTorrent para poder bajarme ficheros el cual estuvo acompañado de otro post para mover ficheros entre el servidor y mi ordenador. Esta vez lo que quiero hacer es usar el server como túnel para evitar contenidos restringidos en el país dónde estoy y mejorar la seguridad en redes abiertas.
Primero de todo tendremos que instalar el software necesario. Para ello ejecutando la siguiente linea en la consola bastará:

wget http://git.io/vpn --no-check-certificate -O openvpn-install.sh; chmod +x openvpn-install.sh; ./openvpn-install.sh

Para los que os gusta hacerlo paso a pasa y configurarlo todo al milímetro al final del post hay un link (en inglés) que os ayudará. Para el resto de mortales el siguiente script lo hace todo, es simplemente un autoinstaller que puede generar claves, revocar certificados y desinstalar OpenVPN.

[code language=”bash”]
#!/bin/bash
# OpenVPN road warrior installer for Debian-based distros

# This script will only work on Debian-based systems. It isn’t bulletproof but
# it will probably work if you simply want to setup a VPN on your Debian/Ubuntu
# VPS. It has been designed to be as unobtrusive and universal as possible.

if [ $USER != ‘root’ ]; then
echo "Sorry, you need to run this as root"
exit
fi

if [ ! -e /dev/net/tun ]; then
echo "TUN/TAP is not available"
exit
fi

if [ ! -e /etc/debian_version ]; then
echo "Looks like you aren’t running this installer on a Debian-based system"
exit
fi

# Try to get our IP from the system and fallback to the Internet.
# I do this to make the script compatible with NATed servers (lowendspirit.com)
# and to avoid getting an IPv6.
IP=$(ifconfig | grep ‘inet addr:’ | grep -v inet6 | grep -vE ‘127\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}’ | cut -d: -f2 | awk ‘{ print $1}’ | head -1)
if [ "$IP" = "" ]; then
IP=$(wget -qO- ipv4.icanhazip.com)
fi

if [ -e /etc/openvpn/server.conf ]; then
while :
do
clear
echo "Looks like OpenVPN is already installed"
echo "What do you want to do?"
echo ""
echo "1) Add a cert for a new user"
echo "2) Revoke existing user cert"
echo "3) Remove OpenVPN"
echo "4) Exit"
echo ""
read -p "Select an option [1-4]: " option
case $option in
1)
echo ""
echo "Tell me a name for the client cert"
echo "Please, use one word only, no special characters"
read -p "Client name: " -e -i client CLIENT
cd /etc/openvpn/easy-rsa/2.0/
source ./vars
# build-key for the client
export KEY_CN="$CLIENT"
export EASY_RSA="${EASY_RSA:-.}"
"$EASY_RSA/pkitool" $CLIENT
# Let’s generate the client config
mkdir ~/ovpn-$CLIENT
cp /usr/share/doc/openvpn/examples/sample-config-files/client.conf ~/ovpn-$CLIENT/$CLIENT.conf
cp /etc/openvpn/easy-rsa/2.0/keys/ca.crt ~/ovpn-$CLIENT
cp /etc/openvpn/easy-rsa/2.0/keys/$CLIENT.crt ~/ovpn-$CLIENT
cp /etc/openvpn/easy-rsa/2.0/keys/$CLIENT.key ~/ovpn-$CLIENT
cd ~/ovpn-$CLIENT
sed -i "s|cert client.crt|cert $CLIENT.crt|" $CLIENT.conf
sed -i "s|key client.key|key $CLIENT.key|" $CLIENT.conf
tar -czf ../ovpn-$CLIENT.tar.gz $CLIENT.conf ca.crt $CLIENT.crt $CLIENT.key
cd ~/
rm -rf ovpn-$CLIENT
echo ""
echo "Client $CLIENT added, certs available at ~/ovpn-$CLIENT.tar.gz"
exit
;;
2)
echo ""
echo "Tell me the existing client name"
read -p "Client name: " -e -i client CLIENT
cd /etc/openvpn/easy-rsa/2.0/
. /etc/openvpn/easy-rsa/2.0/vars
. /etc/openvpn/easy-rsa/2.0/revoke-full $CLIENT
# If it’s the first time revoking a cert, we need to add the crl-verify line
if grep -q "crl-verify" "/etc/openvpn/server.conf"; then
echo ""
echo "Certificate for client $CLIENT revoked"
else
echo "crl-verify /etc/openvpn/easy-rsa/2.0/keys/crl.pem" >> "/etc/openvpn/server.conf"
/etc/init.d/openvpn restart
echo ""
echo "Certificate for client $CLIENT revoked"
fi
exit
;;
3)
apt-get remove –purge -y openvpn openvpn-blacklist
rm -rf /etc/openvpn
rm -rf /usr/share/doc/openvpn
sed -i ‘/–dport 53 -j REDIRECT –to-port/d’ /etc/rc.local
sed -i ‘/iptables -t nat -A POSTROUTING -s 10.8.0.0/d’ /etc/rc.local
echo ""
echo "OpenVPN removed!"
exit
;;
4) exit;;
esac
done
else
echo ‘Welcome to this quick OpenVPN "road warrior" installer’
echo ""
# OpenVPN setup and first user creation
echo "I need to ask you a few questions before starting the setup"
echo "You can leave the default options and just press enter if you are ok with them"
echo ""
echo "First I need to know the IPv4 address of the network interface you want OpenVPN"
echo "listening to."
read -p "IP address: " -e -i $IP IP
echo ""
echo "What port do you want for OpenVPN?"
read -p "Port: " -e -i 1194 PORT
echo ""
echo "Do you want OpenVPN to be available at port 53 too?"
echo "This can be useful to connect under restrictive networks"
read -p "Listen at port 53 [y/n]: " -e -i n ALTPORT
echo ""
echo "Finally, tell me your name for the client cert"
echo "Please, use one word only, no special characters"
read -p "Client name: " -e -i client CLIENT
echo ""
echo "Okay, that was all I needed. We are ready to setup your OpenVPN server now"
read -n1 -r -p "Press any key to continue…"
apt-get update
apt-get install openvpn iptables openssl -y
cp -R /usr/share/doc/openvpn/examples/easy-rsa/ /etc/openvpn
# easy-rsa isn’t available by default for Debian Jessie and newer
if [ ! -d /etc/openvpn/easy-rsa/2.0/ ]; then
wget –no-check-certificate -O ~/easy-rsa.tar.gz https://github.com/OpenVPN/easy-rsa/archive/2.2.2.tar.gz
tar xzf ~/easy-rsa.tar.gz -C ~/
mkdir -p /etc/openvpn/easy-rsa/2.0/
cp ~/easy-rsa-2.2.2/easy-rsa/2.0/* /etc/openvpn/easy-rsa/2.0/
rm -rf ~/easy-rsa-2.2.2
rm -rf ~/easy-rsa.tar.gz
fi
cd /etc/openvpn/easy-rsa/2.0/
# Let’s fix one thing first…
cp -u -p openssl-1.0.0.cnf openssl.cnf
# Fuck you NSA – 1024 bits was the default for Debian Wheezy and older
sed -i ‘s|export KEY_SIZE=1024|export KEY_SIZE=2048|’ /etc/openvpn/easy-rsa/2.0/vars
# Create the PKI
. /etc/openvpn/easy-rsa/2.0/vars
. /etc/openvpn/easy-rsa/2.0/clean-all
# The following lines are from build-ca. I don’t use that script directly
# because it’s interactive and we don’t want that. Yes, this could break
# the installation script if build-ca changes in the future.
export EASY_RSA="${EASY_RSA:-.}"
"$EASY_RSA/pkitool" –initca $*
# Same as the last time, we are going to run build-key-server
export EASY_RSA="${EASY_RSA:-.}"
"$EASY_RSA/pkitool" –server server
# Now the client keys. We need to set KEY_CN or the stupid pkitool will cry
export KEY_CN="$CLIENT"
export EASY_RSA="${EASY_RSA:-.}"
"$EASY_RSA/pkitool" $CLIENT
# DH params
. /etc/openvpn/easy-rsa/2.0/build-dh
# Let’s configure the server
cd /usr/share/doc/openvpn/examples/sample-config-files
gunzip -d server.conf.gz
cp server.conf /etc/openvpn/
cd /etc/openvpn/easy-rsa/2.0/keys
cp ca.crt ca.key dh2048.pem server.crt server.key /etc/openvpn
cd /etc/openvpn/
# Set the server configuration
sed -i ‘s|dh dh1024.pem|dh dh2048.pem|’ server.conf
sed -i ‘s|;push "redirect-gateway def1 bypass-dhcp"|push "redirect-gateway def1 bypass-dhcp"|’ server.conf
sed -i "s|port 1194|port $PORT|" server.conf
# Obtain the resolvers from resolv.conf and use them for OpenVPN
cat /etc/resolv.conf | grep -v ‘#’ | grep ‘nameserver’ | grep -E -o ‘[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}’ | while read line; do
sed -i "/;push \"dhcp-option DNS 208.67.220.220\"/a\push \"dhcp-option DNS $line\"" server.conf
done
# Listen at port 53 too if user wants that
if [ $ALTPORT = ‘y’ ]; then
iptables -t nat -A PREROUTING -p udp -d $IP –dport 53 -j REDIRECT –to-port $PORT
sed -i "/# By default this script does nothing./a\iptables -t nat -A PREROUTING -p udp -d $IP –dport 53 -j REDIRECT –to-port $PORT" /etc/rc.local
fi
# Enable net.ipv4.ip_forward for the system
sed -i ‘s|#net.ipv4.ip_forward=1|net.ipv4.ip_forward=1|’ /etc/sysctl.conf
# Avoid an unneeded reboot
echo 1 > /proc/sys/net/ipv4/ip_forward
# Set iptables
iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -j SNAT –to $IP
sed -i "/# By default this script does nothing./a\iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -j SNAT –to $IP" /etc/rc.local
# And finally, restart OpenVPN
/etc/init.d/openvpn restart
# Let’s generate the client config
mkdir ~/ovpn-$CLIENT
# Try to detect a NATed connection and ask about it to potential LowEndSpirit
# users
EXTERNALIP=$(wget -qO- ipv4.icanhazip.com)
if [ "$IP" != "$EXTERNALIP" ]; then
echo ""
echo "Looks like your server is behind a NAT!"
echo ""
echo "If your server is NATed (LowEndSpirit), I need to know the external IP"
echo "If that’s not the case, just ignore this and leave the next field blank"
read -p "External IP: " -e USEREXTERNALIP
if [ $USEREXTERNALIP != "" ]; then
IP=$USEREXTERNALIP
fi
fi
# IP/port set on the default client.conf so we can add further users
# without asking for them
sed -i "s|remote my-server-1 1194|remote $IP $PORT|" /usr/share/doc/openvpn/examples/sample-config-files/client.conf
cp /usr/share/doc/openvpn/examples/sample-config-files/client.conf ~/ovpn-$CLIENT/$CLIENT.conf
cp /etc/openvpn/easy-rsa/2.0/keys/ca.crt ~/ovpn-$CLIENT
cp /etc/openvpn/easy-rsa/2.0/keys/$CLIENT.crt ~/ovpn-$CLIENT
cp /etc/openvpn/easy-rsa/2.0/keys/$CLIENT.key ~/ovpn-$CLIENT
cd ~/ovpn-$CLIENT
sed -i "s|cert client.crt|cert $CLIENT.crt|" $CLIENT.conf
sed -i "s|key client.key|key $CLIENT.key|" $CLIENT.conf
tar -czf ../ovpn-$CLIENT.tar.gz $CLIENT.conf ca.crt $CLIENT.crt $CLIENT.key
cd ~/
rm -rf ovpn-$CLIENT
echo ""
echo "Finished!"
echo ""
echo "Your client config is available at ~/ovpn-$CLIENT.tar.gz"
echo "If you want to add more clients, you simply need to run this script another time!"
fi
[/code]

“Happy tunneling

Bonus: Para los que os guste un poco más el heavy metal aquí un tutorial paso a paso con explicaciones más detalladas.

Como usar rtorrent des de cero

Viviendo en Alemania no puedo usar bitorrent sin que me llegue una factura por más de 500€ por bajar contenido que tiene copyright. Por lo que finalmente conseguí un servidor dónde tal cosa puede hacerse. El problema es que no tengo GUI por lo que tuve que buscar un cliente bittorrent para bajarme las cosas. Sin GUI, rtorrent era la primera opción que encontré. Al principio parece un poco complicado pero sabiendo los cuatro comandos básicos no ocasiona problemas.

Para iniciar el cliente de torrent:

$ rtorrent

Para poner un archivo en la cola de descargas tienes que presionar intro, pegar el enlace de magnet y darle a intro otra vez.
Una vez has hecho esto tienes el archivo en espera por lo que para iniciarlo usas las flechas arriba y abajo para localizar el archivo y con Control+S empiezas la descarga.
Si por algún motivo te dice que has movido el archivo (a mi me lo dice sin motivo) lo puedes solucionar con Control+E. Puedes cerrar el programa con Control+Q.
El fichero de configuración tiene que colocarse en ~/.rtorrent.rc y yo tengo el siguiente (por si lo quieres usar de base o del que me copié).

# This is an example resource file for rTorrent. Copy to
 # ~/.rtorrent.rc and enable/modify the options as needed. Remember to
 # uncomment the options you wish to enable.
 # Maximum and minimum number of peers to connect to per torrent.
 min_peers = 1
 max_peers = 20
 # Same as above but for seeding completed torrents (-1 = same as downloading)
 min_peers_seed = 1
 max_peers_seed = 20
 # Maximum number of uploads single torrent may use
 max_uploads = 10
 # Maximum number of simultaneous downloads
 max_downloads_global = 10
 # Maximum number of simultaneous uploads
 max_uploads_global = 20
 # Global upload and download rate in KiB. "0" for unlimited.
 download_rate = 0
 upload_rate = 300
 # Default directory to save the downloaded torrents.
 directory = /home/rocreguant/rTorrStuff/Downloads
 # Default session directory. Make sure you don't run multiple instance
 # of rtorrent using the same session directory. Perhaps using a
 # relative path?
 session = /home/rocreguant/rTorrStuff/session
 # Watch a directory for new torrents, and stop those that have been
 # deleted.
 schedule = watch_directory,5,5,load_start=./rtactive/*.torrent
 schedule = tied_directory,6,5,start_tied=
 schedule = untied_directory,7,5,stop_untied=
 # Close torrents when diskspace is low.
 schedule = low_diskspace,5,60,close_low_diskspace=2000M
 # Periodically save session data
 schedule = session_save,240,300,session_save=
 # Enable the default ratio group.
 ratio.enable=
 # Change the limits, the defaults should be sufficient.
 # Upload to a minimum ratio of 4.0
 ratio.min.set=400
 # Upload to a maximum ratio of 20.0
 ratio.max.set=2000
 # Upload a minimum of 250 MB
 ratio.upload.set=250M
 # When seeding ratio is reached close the torrent
 system.method.set = group.seeding.ratio.command, d.close=
 # Move files to ./unsorted when download completes
 system.method.set_key = event.download.finished,move_complete,"execute=mv,-n,$d.get_base_path=,./unsorted/;d.set_directory=./unsorted/"
 # Port range to use for listening.
 port_range = 60125-64125
 # Start opening ports at a random position within the port range.
 port_random = yes
 # Encryption options, set to none (default) or any combination of the following:
 # allow_incoming, try_outgoing, require, require_RC4, enable_retry, prefer_plaintext
 #
 # The example value allows incoming encrypted connections, starts unencrypted
 # outgoing connections but retries with encryption if they fail, preferring
 # plaintext to RC4 encryption after the encrypted handshake
 #
 encryption = allow_incoming,try_outgoing,enable_retry,prefer_plaintext
 # Sort the main view by ratio
 view.sort_current = main,greater=d.get_ratio=
 view.sort_new = main,less=d.get_ratio=
 view.sort = main
 # Sort the seeding view by the upload rate and only show torrents with peers
 view.sort_current = seeding,greater=d.get_up_rate=
 view.filter = seeding,"and=d.get_complete=,d.get_peers_connected="
 view.sort_new = seeding,less=d.get_up_rate=
 view.sort = seeding
 # Sort the leeching view by name
 view.sort_current = leeching,greater=d.get_name=
 view.sort_new = leeching,greater=d.get_name=
 view.sort = leeching
 # Filter the active view by connected peers
 view.sort_current = active,less=d.get_name=
 view.sort_new = leeching,less=d.get_name=
 view.filter = active,d.get_peers_connected=
 view.sort = active
 schedule = sort_main,11,5,view.sort=main
 schedule = sort_seeding,12,5,view.sort=seeding
 schedule = sort_leeching,13,5,view.sort=leeching
 schedule = sort_active,14,5,view.sort=active
 # Enable DHT support for trackerless torrents or when all trackers are down.
 # May be set to "disable" (completely disable DHT), "off" (do not start DHT),
 # "auto" (start and stop DHT as needed), or "on" (start DHT immediately).
 # The default is "off". For DHT to work, a session directory must be defined.
 #
 #dht = auto
 # UDP port to use for DHT.
 #
 dht_port = 63425
 # Enable peer exchange (for torrents not marked private)
 #
 #peer_exchange = yes

Git avanzado: Etiquetas, logs y el botón del pánico

Una vez inicializado git, conocidos los primeros comandos y aprendido a hacer ramas con git ahora toca aprender un poco sobre etiquetas (tags), logs y que hacer cuando la lías parda.

Las etiquetas sirven básicamente para etiquetar commits. ¿Y para que quiere uno etiquetar commits? Bien, pues para indicar en que momento se definió una versión de la aplicación. Para crear una etiqueta usaremos:

 git tag NumeroVersion idCommit

El id del Commit son los primeros 10 caracteres del commit al que queremos etiquetar. Te preguntarás, ¿y como se esos 10 caracteres? Pues fácil te vas al log, y para ver el log usarás el comando:

 git log

Si quieres algo más sofisticado y con menos ruido puedes filtrar por autor:

 git log --author=NombreUsuario

Sólo que archivos fueron cambiados:

 git log –name-status

O si aun así quieres ver todo el árbol con todas las ramas y etiquetas puedes usar el comando:

 git log --graph --oneline --decorate --all

En cualquier caso si quieres indagar más profundamente échale una ojeada a:

 git log --help

En el hipotético caso de que la hayas liado parda y no sepas como solucionar el problema eliminando todos los cambios locales y commits hechos trayendo la versión de la rama master más reciente. Ten en cuenta que sobre-escribirás todos tus ficheros, pero si aun así lo deseas deberás usar los siguientes comandos:

 git fetch origin
 git reset --hard origin/master

Para los que hayáis llegado tan lejos decir que git tiene incorporado algo parecido a una interfaz gráfica. Recordar que no hay para linux una GUI que permita hacer push y toda la mandanga, solo está en Mac y WIndows. Pero para acceder a su sucedáneo se puede acceder escribiendo en la consola:

gitk

Pero si aun así preferís seguir usando la linea de comandos quizás os interese colorear un poco el output con el comando

git config color.ui true

o en los logs simplemente mostrar sólo una linea por commit con:

 git config format.pretty oneline

Como crear ramas (branches) con git

Ahora que ya tenemos git inicializado  y hemos aprendido unos primeros pasos tocará empezar con unos conceptos un poco más avanzados. En este post aprenderemos a crear ramas. Normalmente los proyectos usan ramas para mantener la rama master “más limpia”, evitar commits a medias y evitar conflictos.

Para que nos entendamos la rama master es la rama principal y en las otras ramas es dónde hacemos los cambios. Para crear una rama empezaremos con:

 git checkout -b NombreRama

Como ya vimos después de aplicar los cambios en nuestra rama tocará subir los cambios al directorio remoto haciendo un:

 git push

Una vez terminados todos los cambios y dar la rama por acabada realizaremos el merge. Que básicamente es mezclar nuestros cambios con la rama master. Para esto usaremos el comando:

git merge nombreRama

Algunas veces esto ocasionará conflictos que deberemos solventar. Para ver los conflictos podemos usar:

 git diff <source_branch> <target_branch>

Y si hemos intentado hacer un “merge” que ha sido fallido debido a los conflictos deberemos volver a hacer un:

git add nombreArchivo

Una vez terminado del todo lo que podemos hacer es volver a la rama master con:

git checkout master

Y finalmente borrar la rama con el comando:

git branch -d feature_x

Cabe mencionar que la rama “no está disponible para terceros” a menos que se haga un push al repositorio remoto. Esto se puede hacer con el comando:

git push origin

Para los que les haya interesado este post sobre como crear ramas (branches) en git quizás les interese indagar un poco más en este [EN] modelo de creación de ramas con git. Haciendo un resumen rápido, tienen la rama principal, luego la rama developer y a partir de aquí crean ramas de features.