Monitorer Apache avec Zabbix

Configuration de Nginx

Le serveur apache doit donner sont status en local via l’url http://localhost/server-status Pour cela, il faut ajouter configurer le vhost localhost comme ci-dessous. Il sera disponible uniquement via localhost:

<VirtualHost 127.0.0.1:80>
    ServerName localhost
    <Location /server-status>
        SetHandler server-status
        Order deny,allow
        Deny from all
        Allow from 127.0.0.1
    </Location>
</VirtualHost>

Configuration de l’agent Zabbix

Dans la configuration de l’agent Zabbix ajouter les paramètres suivant pour remonter au serveur les nouvelles clefs

UserParameter=apache.freeworkers,curl -s http://localhost/server-status?auto | grep ^Score | grep -o '\.' | wc -l
UserParameter=apache.status[*],curl -s http://localhost/server-status?auto | awk '/$1: / {print $NF}' | sed 's/^\./0./g'

Import du template

Télécharger et importer zbx_templates_apache.xml dans vos modèles Ce template contient toutes les clefs, deux graphiques et deux triggers :

  • Graphiques
    • Apache Bytes
    • Apache Threads
  • Triggers
    • 10% worker ilde available on {HOST.NAME}
    • Apache on {HOST.NAME} has just been restarted

Have fun :)


Monitorer Nginx avec Zabbix

Configuration de Nginx

Le serveur nginx doit donner sont status en local via l’url http://localhost:61123/nginx_status
Pour cela, il faut ajouter le « server » suivant qui sera disponible uniquement via localhost sur le port 61123:

server {
        listen       127.0.0.1:61123;
        server_name  localhost;
        location /nginx_status {
                stub_status on;
                access_log   off;
                allow 127.0.0.1;
                deny all;
        }
}

Configuration de l’agent Zabbix

Dans la configuration de l’agent Zabbix ajouter les paramètres suivant pour remonter au serveur les nouvelles clefs

UserParameter=nginx.active[*],curl -s http://localhost:61123/nginx_status | awk '/^Active/ {print $NF}'
UserParameter=nginx.reading[*],curl -s http://localhost:61123/nginx_status | awk '/Reading/ {print $$2}'
UserParameter=nginx.writing[*],curl -s http://localhost:61123/nginx_status | awk '/Writing/ {print $$4}'
UserParameter=nginx.waiting[*],curl -s http://localhost:61123/nginx_status | awk '/Waiting/ {print $$6}'
UserParameter=nginx.accepted[*],curl -s http://localhost:61123/nginx_status | awk '/^[ \t]+[0-9]+[ \t]+[0-9]+[ \t]+[0-9]+/ {print $$1}'
UserParameter=nginx.handled[*],curl -s http://localhost:61123/nginx_status | awk '/^[ \t]+[0-9]+[ \t]+[0-9]+[ \t]+[0-9]+/ {print $$2}'
UserParameter=nginx.requests[*],curl -s http://localhost:61123/nginx_status | awk '/^[ \t]+[0-9]+[ \t]+[0-9]+[ \t]+[0-9]+/ {print $$3}'

Import du template

Télécharger et importer zbx_templates_nginx.xml dans vos modèles

Ce template contient toutes les clefs et deux graphiques :

  • Nginx current connections
  • Nginx requests

Have fun :)


Protection contre le hotlinking avec Varnish

Voici un exemple de condition à ajouter dans votre vcl recv pour protéger un dossier d’un site :

if (req.http.host == "le.domaine.a.proteger.ltd" && req.url ~ "^/l/uri/a/proteger" && (req.http.referer && req.http.referer !~ "^http://le.domaine.a.proteger.ltd/")) {
    error 403 "No hotlinking please";
}

Remplacer :

  • le.domaine.a.proteger.ltd par le domaine (attention si votre site est accessible avec et sans www)
  • /l/uri/a/proteger : par l’uri à protéger, supprimer cette partie si vous voulez protéger l’intégralité du site

Pour mettre en place le même type de protection via apache, voir cet article : Un htaccess pour les pompeurs de sites dans lequel est expliqué comment procéder avec des règles de réécriture Apache


FreeBSD 10.0 sur une RaspberryPI rev. B

Voici comment « bsdiser » votre Raspberry :

  1. Téléchargez l’image : FreeBSD-10.0-STABLE-arm-armv6-RPI-B-20140127-r261200.img.bz2 ou plus récente sur un miroir FreeBSD
  2. Copier l’image sur votre SD avec dd :
    bunzip2 -c FreeBSD-10.0-STABLE-arm-armv6-RPI-B-20140127-r261200.img.bz2 | dd of=/dev/votresd bs=1M
  3. Une fois la BSD en ligne :
    1. SSH sera lancé
    2. Le compte root n’as pas de mot de passe (vous ne pourrez pas vous y connecter en ssh sans changer le mot de passe)
    3. Le clavier est en qwerty
    4. L’interface réseau est en DHCP

Si vous voulez faire l’image vous même, voici un article (en anglais) qui explique comment procéder et comment compiler le kernel : http://blog.khubla.com/freebsd/creating-a-custom-freebsd-build-for-raspberry-p


« Visualizer » Spotify

Si il y a bien une Feature qui manquait a spotify, c’est celle ci, avoir un visualizer intégré dans son Spotify.

Ils l’ont enfin développé et cela fonctionne pour les Mac, Linux et Windaube Windows :


spotify-visualizer

L’annonce a été faite le 14 novembre sur leur blog et cela n’est pas fait a moitié car, le code source et la documentation sont disponible :

Code: https://github.com/spotify/visualizer-app
Docs: https://developer.spotify.com/docs/apps/api/1.0/api-audio.html

Je n’ai pas l’impression qu’on puisse le mettre en plein écran.


Connaitre son IP public via une requete DNS

Sous Linux

dig +short myip.opendns.com @resolver1.opendns.com

Vous pouvez vous faire un alias du type

monip="dig +short myip.opendns.com @resolver1.opendns.com"

Sous Windows

Dans une console (de memoire):

nslookup
server resolver1.opendns.com
myip.opendns.com

Motion – envoyer les videos sur Google Drive

J’ai mit en place Motion sur ma Raspberry PI pour faire un système de vidéo surveillance qui enregistre une vidéo uniquement lorsqu’il y a un mouvement.

Pour cela, j’ai installé Raspbian sur ma  Raspberry PI puis le packet motion après avoir branché une webcam compatible en USB.

Pour que le script fonctionne, vous devez installer ffmpeg et python-gdata.

  • ffmpeg – Multimedia player, server, encoder and transcoder (transitional package)
    • Je l’utilise pour ré-encoder l’avi généré
  • python-gdata – Google Data Python client library

Descriptions des fichiers utilisé

/etc/motion/motion.conf

Fichier de configuration du daemon motion.

  • videodevice : indiquer votre webcam
  • v4l2_palette : la palette à utiliser (17 correspond a celle pour une PlayStation Eye)
  • target_dir : est l’emplacement ou la vidéo sera écrite, dans mon cas, je la met sur mon NAS pour ne pas utiliser la SD-CARD
  • on_movie_end : commande a exécuter dés qu’une vidéo est écrite.

/home/pascal/bin/motion_upload.sh

Ce petit script ré-encode la vidéo puis lance uploader.py

/home/pascal/bin/uploader.py

Script écrit par Jeremy Blythe que j’ai corrigé, il avait fait une boucle sur tous les fichiers de votre google drive pour vérifier que le dossier de destination existe, j’ai remplacé cela par une recherche via gdata

/home/pascal/bin/uploader.conf

Fichier de configuration du script Python à completer avec vos identifiants Google.
N’oubliez pas de définir la variable folder avec le « dossier » Google Drive de destination

Les fichiers de configurations et scripts

/etc/motion/motion.conf

daemon on
process_id_file /var/run/motion/motion.pid
setup_mode off
videodevice /dev/video0
v4l2_palette 17
input 8
norm 0
frequency 0
rotate 0
width 640
height 480
framerate 3
minimum_frame_time 0
netcam_tolerant_check off
auto_brightness on
brightness 0
contrast 0
saturation 0
hue 0
roundrobin_frames 1
roundrobin_skip 1
switchfilter off
threshold 1500
threshold_tune on
noise_level 32
noise_tune on
despeckle EedDl
smart_mask_speed 0
lightswitch 0
minimum_motion_frames 2
pre_capture 1
post_capture 1
gap 60
max_mpeg_time 0
output_all off
output_normal first
output_motion off
quality 75
ppm off
ffmpeg_cap_new on
ffmpeg_cap_motion off
ffmpeg_timelapse 0
ffmpeg_timelapse_mode daily
ffmpeg_bps 500000
ffmpeg_variable_bitrate 0
ffmpeg_video_codec mpeg4
ffmpeg_deinterlace off
snapshot_interval 0
locate on
text_right %Y/%m/%d\n%T %q
text_changes off
text_event %Y/%m/%d %T
text_double off
target_dir /media/nas/Private/motion
snapshot_filename %Y-%m-%d_%H%M%S-%v-snapshot
jpeg_filename %Y-%m-%d_%H%M%S-%v-%q
movie_filename %Y-%m-%d_%H%M%S-%v
timelapse_filename %Y-%m-%d_timelapse
webcam_port 8080
webcam_quality 75
webcam_motion off
webcam_maxrate 1
webcam_localhost on
webcam_limit 0
control_port 0
control_localhost on
control_html_output on
track_type 0
track_auto off
track_motorx 0
track_motory 0
track_maxx 0
track_maxy 0
track_iomojo_id 0
track_step_angle_x 10
track_step_angle_y 10
track_move_wait 10
track_speed 255
track_stepsize 40
quiet on
on_movie_end /home/pascal/bin/motion_upload.sh %f
night_compensate on
sql_log_image on
sql_log_snapshot on
sql_log_mpeg off
sql_log_timelapse off
sql_query insert into security(camera, filename, frame, file_type, time_stamp, event_time_stamp) values('%t', '%f', '%q', '%n', '%Y-%m-%d %T', '%C')

/home/pascal/bin/motion_upload.sh

#!/usr/bin/env sh

FILE=$(echo $1 | cut -d'.' -f1 ); do

/usr/bin/avconv -i "$FILE.avi" -vcodec mpeg4 -an -preset fast "$FILE.mp4" 1>/dev/null 2>&1
rm $FILE.avi
/home/pascal/bin/uploader.py /home/pascal/bin/uploader.conf $FILE.mp4 && rm $FILE.mp4

/home/pascal/bin/uploader.py

#!/usr/bin/python2.7
'''
Created on 6 Jun 2012
Modified on 10 Jan 2014

@author: Jeremy Blythe
@author: Pascal A.

Motion Uploader - uploads videos to Google Drive

Read the blog entry at http://jeremyblythe.blogspot.com and/or http://notes.depad.fr for more information
'''

import smtplib
from datetime import datetime

import os.path
import sys

import gdata.data
import gdata.docs.data
import gdata.docs.client
import ConfigParser

class MotionUploader:
    def __init__(self, config_file_path):
        # Load config
        config = ConfigParser.ConfigParser()
        config.read(config_file_path)

        # GMail account credentials
        self.username = config.get('gmail', 'user')
        self.password = config.get('gmail', 'password')
        self.from_name = config.get('gmail', 'name')
        self.sender = config.get('gmail', 'sender')

        # Recipient email address (could be same as from_addr)
        self.recipient = config.get('gmail', 'recipient')

        # Subject line for email
        self.subject = config.get('gmail', 'subject')

        # First line of email message
        self.message = config.get('gmail', 'message')

        # Folder (or collection) in Docs where you want the videos to go
        self.folder = config.get('docs', 'folder')

        # Options
        self.delete_after_upload = config.getboolean('options', 'delete-after-upload')
        self.send_email = config.getboolean('options', 'send-email')

        self._create_gdata_client()

    def _create_gdata_client(self):
        """Create a Documents List Client."""
        self.client = gdata.docs.client.DocsClient(source='motion_uploader')
        self.client.http_client.debug = False
        self.client.client_login(self.username, self.password, service=self.client.auth_service, source=self.client.source)

    def _get_folder_resource(self):
        """Return the resource for given folder."""

        # Create a query matching exactly a title, and include collections
        q = gdata.docs.client.DocsQuery(
            title=self.folder,
            title_exact='true',
            show_collections='true'
            )
        # Execute the query and get the first entry
        resource = self.client.GetResources(q=q).entry[0]

        if resource.title.text == self.folder:
            col = resource
        return col

    def _send_email(self,msg):
        '''Send an email using the GMail account.'''
        senddate=datetime.strftime(datetime.now(), '%Y-%m-%d')
        m="Date: %s\r\nFrom: %s <%s>\r\nTo: %s\r\nSubject: %s\r\nX-Mailer: My-Mail\r\n\r\n" % (senddate, self.from_name, self.sender, self.recipient, self.subject)
        server = smtplib.SMTP('smtp.gmail.com:587')
        server.starttls()
        server.login(self.username, self.password)
        server.sendmail(self.sender, self.recipient, m+msg)
        server.quit()

    def _upload(self, video_file_path, folder_resource):
        '''Upload the video and return the doc'''
        doc = gdata.docs.data.Resource(type='video', title=os.path.basename(video_file_path))
        media = gdata.data.MediaSource()
        media.SetFileHandle(video_file_path, 'video/mp4')
        doc = self.client.CreateResource(doc, media=media, collection=folder_resource)
        return doc

    def upload_video(self, video_file_path):
        """Upload a video to the specified folder. Then optionally send an email and optionally delete the local file."""
        folder_resource = self._get_folder_resource()
        if not folder_resource:
            raise Exception('Could not find the %s folder' % self.folder)

        doc = self._upload(video_file_path, folder_resource)

        if self.send_email:
            video_link = None
            for link in doc.link:
                if 'video.google.com' in link.href:
                    video_link = link.href
                    break
            # Send an email with the link if found
            msg = self.message
            if video_link:
                msg += '\n\n' + video_link
            self._send_email(msg)

        if self.delete_after_upload:
            os.remove(video_file_path)

if __name__ == '__main__':
    try:
        if len(sys.argv) < 3:
            exit('Motion Uploader - uploads videos to Google Drive\n   by Jeremy Blythe (http://jeremyblythe.blogspot.com)\n\n   Usage: uploader.py {config-file-path} {video-file-path}')
        cfg_path = sys.argv[1]
        vid_path = sys.argv[2]
        if not os.path.exists(cfg_path):
            exit('Config file does not exist [%s]' % cfg_path)
        if not os.path.exists(vid_path):
            exit('Video file does not exist [%s]' % vid_path)
        MotionUploader(cfg_path).upload_video(vid_path)
    except gdata.client.BadAuthentication:
        exit('Invalid user credentials given.')
    except gdata.client.Error:
        exit('Login Error')
    except Exception as e:
        exit('Error: [%s]' % e)

/home/pascal/bin/uploader.conf

[gmail]
# GMail account credentials
name =
user =
password =
sender =

# Recipient email address (could be same as from_addr)
recipient =

# Subject line for email
subject = Motion detected

# First line of email message
message = Video uploaded

[docs]
# Folder (or collection) in Docs where you want the videos to go
folder = motion

[options]
# Delete the local video file after the upload
delete-after-upload = true

# Send an email after the upload
send-email = true

Article basé sur http://jeremyblythe.blogspot.com


Gérer la swap de ca Raspberry PI

Raspbian ne créé pas de partition pour la swap, dphys est utilisé pour générer un fichier.

  1. Définissez la taille du fichier de swap désiré dans le fichier /etc/dphys-swapfile
  2. (Re-)Générer le fichier avec la commande dphys-swapfile setup
  3. Désactiver votre swap si elle est active avec dphys-swapfile swapoff
  4. Puis réactiver la avec la nouvelle taille grâce à dphys-swapfile swapon

OSx Mavericks : Créer un disque USB Bootable 2

Créer un média d’installation a partir de l’installer téléchargé sur l’apple store est simple, il vous faut lancer une commande en mode console et avoir :

  • un minimum de 8Go
  • le format doit être de type « Mac OS étendu (journalisé)« 
  • la clé dans mon exemple s’appele « Mavericks« 

Vous n’etes pas obligé de formatter votre disque USB, Clé ou autre périférique de stockage externe, l’executable le fera pour vous

Voici la commande et la sortie de la console :

 % sudo /Applications/Install\ OS\ X\ Mavericks.app/Contents/Resources/createinstallmedia --volume /Volumes/OSx --applicationpath /Applications/Install\ OS\ X\ Mavericks.app

Password:
Ready to start.
To continue we need to erase the disk at /Volumes/Mavericks.
If you wish to continue type (Y) then press return: Y
Erasing Disk: 0%... 10%... 20%... 30%...100%...
Copying installer files to disk...
Copy complete.
Making disk bootable...
Copying boot files...
Copy complete.
Done.