Automatic chef node register on server provisioning
When I started playing with chef, I rapidly came to a question. How can I do to automate the new nodes registration on chef server when creating new virtual instances?
I have a few server images. All my images have chef-client and the necessary files to do a bootstrap client setup installed.
Besides these files I have a small “init” script and a config file for this script.
The script basically run the bootstrap chef-client set up with chef-solo and restart the chef-client. If the process goes well, it removes the server validation.pem stored in /etc/chef/ and makes sure that the script is not going to run anymore by setting a config variable.
Here is the config file:
and here is the “init” script:
I believe that there are a lot of approaches, and maybe better than mine. For example, mine is not valid if you are going to use it with public AMI in amazon. Even if these AMIs have chef-client installed you must provide your server validation.key. The best solution in this case would be to make a SSH connection to the new server right after it starts and copy the validation.pem and the necessary chef configurations.
Conditional relayhost in Postfix
Let’s suposse that your server sends all the mail through a relayhost. But you need emails to a specific domain to be sent directly without passing by the relayhost. To solve this problem you need to configure your transport table with different nexthops depending on the destination domain.
For example, if I want to send directly emails to gmail.com accounts. And I want the rest of emails to be sent through a relayhost in my network (10.0.0.5), I need to write this transport table config file:
gmail.com : * smtp:10.0.0.5
Don’t forget to postmap the transportsf file and include the transport_maps config parameter in your main.cf:
transport_maps = hash:/etc/postfix/transport
Command to check a Syslog server status from Nagios
I’ve been using Nagios for a long time and now I have to check a Syslog server. I was looking for a command to check directly a remote Syslog server.
I didn’t find anything that fit my needs so I did one by myself.
To use this command, the Syslog server has to bee listening on the UDP 514 port. It’s only made to check Syslog servers that are available on a network.
The process is simple:
- The script sends a message to the syslog server
- The script start a small UDP server on localhost
- The remote syslog server receives the message and sends it back to the server where the script was executed from
- The script UDP server receives the message and check if it is correct
The Syslog server needs to know how to match the specific message from the check script and send it back to the source script, so it needs a small previous configuration.
The code is hosted in github. There you cand find detailed information about how to run this script and how to configure a Syslog server in the README file.
http://github.com/lbosque/check_syslog
You can also clone directly the repository and see the README with your favourite editor:
git://github.com/lbosque/check_syslog.git
Vacation script for email server
Sometimes I have the need to install some kind of auto-respond feature on an email server. I already used a few times gnarwl.
Honestly, I don’t like it. I spent a lot of time debugging and some parts of it made me crazy. Of course, it’s only my opinion and admit that there are a lot of work put on that project.
Nevertheless I decided to make my own vacation script. The idea was to make something very easy to use and install, and also something easy to hack. I assume certain behaviours so I don’t relay on the configuration file for a lot of things. This way, it results in a very simple configuration file.
I still want to add some features, but only the necessary to have a quality script without turning it in a very complex script.
The code is hosted in github. There you can rea the README file to more information about how it works and how to install it.
http://github.com/lbosque/simple_vacation
You can also clone directly the repository and see the README with your favourite editor:
git clone git://github.com/lbosque/simple_vacation.git
It would be great to have any kind of feedback that helps me to improve the code. Of course you can contact me for any kind of doubt or comment.
Default server in nginx
By default nginx accepts requests from any domain that points to the nginx server. If you want that only requests from domains that are configured in nginx be processed you cand add a default rule in nginx:
server {
listen 80 default;
server_name _;
deny all;
}
So, if you try to do a request from a domain not configured in nginx, it will return a 403 status (forbidden)
LDAP: Introduction
This is the first post of a LDAP posts collection where I’ll try to explain all what I learned about this technology for the last years.
What is LDAP?
LDAP stands for Lightweight Directory Access Protocol.
LDAP is not a database
LDAP is A protocol to handle information from a Database
One of the most common applications of LDAP is as an authentication backend for an email server. Next, we can see an example:
In this picture a happy user tries to check his email from his personal computer. So he sends his login information to the email server. The email server fetches this data and starts talking with the LDAP server. The LDAP server contains all the users information, so if the login information that it is receiving from the mail server matches the information of any user in its database, it is going to return a positive answer to the email server. At this point, the email server knows that the user sent a valid login information, so it will send him his new emails.
In the picture we can see that the email server doesn’t know the physical database where the users information is stored. It only speaks with the LDAP server, and later the LDAP server try to compare the information with the database backend.
LDAP is extremely fast reading and searching information in the database. This is because the elements in a LDAP directory are arranged in a hierarchical tree, so searches are made always downwards. Because of that, LDAP is widely used as an authentication backend for all kind of services, specially the ones with a big amount of users. Write operations are not so fast, but in this kind of applications, users are used to read their personal information from the database, but not to change it.
Data types
In spite of being a hierarchical tree, all elements in the tree are equal. An element has one or more objeClasses that define the element purpose. Every objectclass has one or more required attributes and one or more optional attributes. So, in the end, an element belongs to one or more objectClasses and has one or more attributes depending on the objectClasses it belongs to.
For example, en element representing a person has the person objectClass. So, this element is required to define the attributes sn (surname) and cn (commonName). But at the same time it could have, if it wants it to, the telephoneNumber attribute.
There are a lot of schemas that let the chance to load any kind of data in the tree. You can also create your own schema if there’s not any schema that satisfies your needs.
Structure
Like I said before, a LDAP directory is built with different kinds of elements arranged in a hierarchical tree structure. All the elements have a DN (Distinguished Name) that is an their identity inside the directory. An element DN is built with their own RDN (Relative Distinguished Name) and the RDN of the parent elements to the top element of the tree. This seems a bit confused, so let’s explain it better. Let’s see a small picture:
This is our directory tree. Let’s suppose that I want this directory to authenticate all of the example.com domain users.
Usually when the top element of a tree is a domain, all the parts of the domain name are stored in separated elements. So, com and example are stored in different elements but following the same order.
The com element has the RDN “dc=com“. His RDN is made up with an element attribute. This elements belongs to the dcObject objectclass. This objectClass defines that all element belonging to it has to set the dc (domainComponent) attribute. This element has more attributes but, the main one is dc so it is part of the RDN.
That is the same case with the element example. It belongs to dcObject objectclass. So its dc attribute is part of its RDN. There is another element above, so this elemend DN would be the sum of its RDN and the parent RDN, “dc=example,dc=com“.
Next we have a simple container. We want to store people information, but we could also want to store, for example, groups information. A group and a person are two different kinds of elements. So in that case we would create two different containers in the tree. One for storing people, and another to store groups.
In this case, we only have the People container. This element belongs to organizationalUnit objectClass. This objectClass force the element to set the ou (organizationalUnitName) attribute. So this element RDN is “ou=People”. And its DN is “ou=People,dc=example,dc=com”.
Finally we have the “cn=Luis” element. This is a person and it belongs to the person objectClass. Like I said before, the person objectClass force the element to set the cn and sn attributes. The cn value is “Luis” and the sn value is “Bosque”. We can choose any element attribute to make the RDN. We choosed the cn attribute, but could be also the sn attribute.
So, this element RDN is “cn=Luis” and its DN is “cn=Luis,ou=People,dc=example,dc=com”.
Important: We can’t have two elements in the tree with the same DN. So, in this specific case, we couldn’t have two people with the name “Luis”. It would be possible to have two people with the same attributes but their DN must be different. For example, we can call one of them Luis and the other Luisico.
We can see a bigger example of a LDAP directory tree. This is onle an example. I mean that you can use a LDAP directory to store any kind of information, not only people information. With the right schemas, you can use a directory to create any kind of data structure.
LDAP Implementations
There are a lot of servers implementing the LDAP protocol. OpenLDAP, Active Directory, Sun ONE Directory Server, Novell Directory Server, Red Hat Directory Server, etc…
I already worked with some of them but I’m used to work with OpenLDAP, so, in the next posts I will focus on OpenLDAP.
When you install OpenLDAP, in a Linux machine for example, it creates a simple BDB database with a few example data. S
Database Backends
There are also several available database backends to use with OpenLDAP like BDB, HDB, LDIF, etc..
When installing OpenLDAP, the server uses a BDB Database. It happens transparently to the user. So, the people that have just met LDAP don’t need to care about the difference between protocol and database.
Just install openldap and start working on it.
Curso de Sistemas Linux en The Cocktail
Voy a dar un curso de sistemas el viernes 16 por la tarde de 16 a 20 horas y el sábado 17 por la mañana de 10 a 14 horas. Va a ser en el aula de las oficinas de The Cocktail en la C/ Salamanca, 17, Madrid.
El curso va a cubrir todo el proceso de puesta en marcha de una máquina con entorno Ruby on Rails en producción. Esto implica los siguientes puntos:
* Instalación y configuración de Debian
* Instalación del stack de Rails
* Estrategias de Deploy
* DNS
* Securización del servidor
* Backups
* Monitorización
* Configuración del servicio de mailing
Estos puntos implican tecnologías como Debian, SSH, DNS, Ruby, Rails, rubygems, rsync, Munin, Postfix, Apache, Passenger, MySQL, Iptables, Bash scripting, IDS, …
La idea es tratar todos estos puntos en cierta profundidad aunque intentando tocar lo justo de ficheros de configuración para no hacer aburrido el curso.
Voy a intentar que el curso sea para todos los niveles. Se tocarán diversos aspectos desde truquillos del día a día y conceptos básicos de todas las tecnologías hasta configuraciones complejas, de una forma más o menos gradual.
A ver si lo conseguimos.
Si tenéis alguna sugerencia es el momento de decírmelo. Estoy totalmente abierto.
Los que os queráis apuntar decídmelo mandándome un email a “luis.bosque ARROBA the-cocktail PUNTO com”. Solo
pido que los que os apuntéis sea porque tenéis claro que queréis asistir a este curso y no por apuntaros por que sí.
Por desgracia hay límite de plazas, por lo que no puedo garantizar que haya sitio para todos.
wordpress.com, wordpress.org, redirections and LinkedIn
I wanted to change my wordpress.com blog to a self-hosted wordpress blog.
This is the scenario:
- My old blog is lbosque.wordpress.com.
- My new blog is blog.luisbosque.com.
- I would like to keep the indexed information in google, so people that open a old indexed post could actually access the information and not receive a 404 status.
- WordPress.com doesn’t offer the posibility of add a 301 redirection in their system to put your blog outside of it, which is totally understandable.
UPDATE: In 2010/05/31 wordpress.com started to do 301 permanent redirections to custom domains.
So, what I did, is this:
- I added an extra domain (blog.luisbosque.com) in my wordpress.com blog. This costs about 10$/year, which is not much money. What I can do with this, is to set the new domain as a primary domain, so when I try to open http://lbosque.wordpress.com, wordpress redirects the request to http://blog.luisbosque.com. Unfortunatelly this is a 302 Redirection which is not a good thing to Google indexing, but there is no choice.
- Next, I installed the last wordpress.org version in my server and imported all the current blog information. Configured the webserver to use the blog.luisbosque.com domain.
- The next step was to change the blog.luisbosque.com DNS zone to point to my new server instead of doing a CNAME to lbosque.wordpress.com. So now when someone try to open http://lbosque.wordpress.com, wordpress.org redirects it to http://blog.luisbosque.com that is actually hosted on my server. My old blog is still hosted in wordpress.com, but because the redirections is no more visible.
So, now, I have to try to change all of my old blog references and wait to Google have indexed the most part of the new blog. Later, I’ll remove the lbosque.wordpress.com blog.
I found a problem when I changed the URL on the LinkedIn WordPress plugin. Within this plugin, you have to enter your wordpress blog URL, and the plugin updates the LinkedIn application with the latest blog posts. This is great, but it has a problem when the domain you enter is in a external hosting, but it is also registered as a wordpress.com domain. The plugin tries to search this blog in the wordpress.com database, so if it finds it (in my case, it does it) it stops looking for it in their real server.
The solution I figured out is to use an auxiliar domain, this way:
- I configure in my web server an auxiliar domain, for example blog.luisbosque.es. I configure it so when someone try to open http://blog.luisbosque.es the webserver do a 301 redirection to http://blog.luisbosque.com
- I change the LinkedIn wordpress plugin blog URL to blog.luisbosque.es. This domain is not registered in the wordpress.com database so the plugin tries to fetch the feeds within my server, which actually redirects the request to the final domain blog.luisbosque.com
The result is that the posts title that appears in the wordpress application within LinkedIn belong to the blog.luisbosque.com domain and not to the blog.luisbosque.es auxiliar domain.
This is not the cleanest solution. It’s a bit tricky, but it works, which it’s enough for me.
Thanks to the fast and useful wordpress support answer, that helped me to figure out how to override this behaviour.
Oferta de Administrador de Sistemas Junior en The Cocktail
The Cocktail es una consultora de internet, enfocada en la experiencia de usuario y diseño de producto, especialista en traducir objetivos de negocio en productos digitales innovadores, usables, atractivos y rentables.
Queremos incorporar a nuestro equipo de trabajo un Administrador de Sistemas Junior con experiencia en manejo de sistemas Linux, redes TCP/IP , y especialmente interés y compromiso por el open source. Realizará las siguientes tareas:
- Administración de servidores *nix – Particularmente Debian.
- Instalación y despliegue de nuevos servidores en producción y en desarrollo. Compilación de software.
- Monitorización y backups.
- Configuración de routers, switches, firewalls y balanceadores de carga.
- Mantenimiento de la red local, accesos remotos VPN y políticas de acceso a recursos.
Los requisitos mínimos son:
- Experiencia administrando sistemas Linux.
- Experiencia con Debian – GNU/Linux, MySQL, Apache.
- Conocimientos sobre redes TCP/IP.
- Interés y compromiso por el open source.
- Facilidad para trabajar en equipo. Auto-disciplina y atención a los detalles. Iniciativa y proactividad.
- Conocimiento e interés por Ruby On Rails y lenguajes de programación dinámicos.
- Experiencia con varias de las siguientes tecnologías: Apache, MySQL, Bash, Ruby, Samba, Postfix, Nagios, Xen, Iptables, Subversion, Git, Rsync, LDAP
Y por supuesto el mayor de los requisitos es que crea que es capaz de desempeñar este trabajo, teniendo en cuenta las responsabilidades arriba mencionadas.
El trabajo es de carácter presencial en las oficinas de Madrid en horario de jornada partida.
Si estás interesado, envía tu CV a: andrea.hidalgo ARROBA the-cocktail PUNTO com
Tagline en el tema journalist de wordpress
He hecho un pequeñito cambio en el tema journalist de Lucian Marin, que es el que uso en este blog.
El cambio lo he aplicado a la última versión en la que, en la cabecera del tema, aparece un diálogo de fondo negro con el tagline del blog. Lo que he hecho es simplemente meterle un if para que no muestre el diálogo si el blog no tiene definido el tagline.
Este cambio hay que aplicárselo al header.php de dicho tema. A continuación pongo el diff del fichero:
19c19,21
< <div id="bubble"><p><?php bloginfo('description'); ?></p></div> <!-- erase this line if you want to turn the bubble off -->
---
> <?php if (strlen(get_bloginfo('description')) > 0) { ?>
> <div id="bubble"><p><?php bloginfo('description'); ?></p></div>
> <?php } ?>


