Featured image of post Installation AWStats avec Ansible

Installation AWStats avec Ansible

Installation de l'analyseur de traffic AWStats dans un containeur LXD avec Ansible

Introduction

AWStats est une alternative libre à Google Analytics qui permet d’analyser le trafic de votre site Internet, de votre serveur de mail ou serveur FTP via une interface Web. Il prend en charge la plupart des serveurs. Le projet est assez ancien, mais complet et très simple à installer ; avec presque aucun pré-requis : Apache et Perl.

L’installation est assez simple. Je vais utiliser ‘ansible’ pour déployer le service dans un container Incus (la procédure sera la même pour un serveur standard).

Nous utiliserons ‘rsyslog’ sur le serveur pour réceptionner les logs des serveurs à analyser.

Hypothèse de travail

J’ai créé au préalable un container Incus basé sur une distribution Debian 12.

Je pars du principe que le serveur SSH est configuré coté serveur pour pouvoir exécuter les scripts ‘ansible’.

Ansible est installé sur votre poste client qui effectuera le déploiement du service ‘AWStats’. Mon répertoire de travail ‘.ansible’ se trouve à la racine du répertoire utilisateur.

Mes fichiers de déploiements ansible seront dans le répertoire : /home/user/.ansible/roles

L’architecture de mes fichiers de configuration ‘ansible’

J’utilise les ‘roles’ pour une structure modulaire et une simplication décritures de mes ‘Playbooks’.

Voici un apercu des fichiers et répertoires nécessaires :

L’architecture des fichiers ansible

La configuration des sources

Configuration des variables globales

Nous allons utilisez un fichier de configuration contenant des variables globale qui seront utilisées dans nos tâches.

Ce fichier est situé dans : config/commun/defaults/main.yml

awstats_src: "https://prdownloads.sourceforge.net/awstats/awstats-7.9.tar.gz"
awstats_dst: "awstats.tar.gz"
awstats_tar: "awstats.tar"
awstats_www: "/var/www/awstats/"
awstats_stats: "{{awstats_www}}/stats/"
awstats_www_config: "{{awstats_www}}/cgi-bin/awstats.conf"
awstats_local_apache_config: "/home/yannick/.ansible/roles/config/awstats/awstats_apache.conf"
awstats_server_apache_config: "/etc/apache2/sites-available/awstats.conf"
awstats_local_app_config: "/home/yannick/.ansible/roles/config/awstats/awstats_app.conf"
awstats_local_rsyslog_config: "/home/yannick/.ansible/roles/config/awstats/rsyslog.conf"
awstats_local_log_rotate_config: "/home/yannick/.ansible/roles/config/awstats/log_rotate_hugo"
awstats_log_rotate_conf: "/etc/logrotate.d/hugo"

La dernière version en cours, est la ‘7.9’ du 17/01/2023.

Remarque : J’ai pris comme exemple l’analyse des logs mon Blog basé sur le moteur ‘Hugo’.

Configuration de la tache

Nous allons utilisés un seul fichier de type ‘tasks’ pour décrire les installations à effectuer. Ce fichier est situé dans config/awstats/tasks/main.yml. Le fichier est assez facile à comprendre ; la logique est toujours la même.

Voici son contenu :

    ---

    - name: "Installation des pre-requis : curl,apache2,libapache2-mod-perl2"
      apt:
        name: "curl,apache2,libapache2-mod-perl2,rsyslog"
        state: "present"

    - name: "Verifie si les sources ont deja ete recuperees"
      stat:
        path: "{{ awstats_dst }}"
      register: rep_source

    - name: "Recuperation des sources"
      command:
        curl -L "{{ awstats_src }}" -o "{{ awstats_dst }}"
      when: not rep_source.stat.exists

    - name: "Verifie si la source a deja ete deccompressee"
      stat:
        path: "{{ awstats_tar }}"
      register: rep_source_tar

    - name: Decompression des sources
      shell: |
        gunzip ./"{{ awstats_dst }}"
        tar -xvf {{ awstats_tar }}
      when: not rep_source_tar.stat.exists

    - name: Verifie si les sources sont dans le répertoire www
      stat:
        path: "{{ awstats_www }}"
      register: rep_wwww

    - name: Copie des sources
      shell: |
        sudo mkdir "{{ awstats_www }}"
        sudo cp -r ./awstats*/wwwroot/* "{{ awstats_www }}"
        sudo chown -R www-data:www-data "{{ awstats_www }}"
      when: not rep_wwww.stat.exists

    - name: Verifie si le fichier de config apache existe
      stat:
        path: "{{ awstats_www_config }}"
      register: config_apache_created

    - name: Copie le fichier de configuration apache
      ansible.builtin.copy:
        src: "{{ awstats_local_apache_config }}"
        dest: "{{ awstats_server_apache_config }}"
        owner: root
        group: root
        mode: '0644'
      when: not config_apache_created.stat.exists

    - name: Verifie si le fichier de config de l'application existe
      stat:
        path: "{{ awstats_www_config }}"
      register: config_www_created

    - name: Copie le fichier de configuration de l'application
      ansible.builtin.copy:
        src: "{{ awstats_local_app_config }}"
        dest: "{{ awstats_www_config }}"
        owner: www-data
        group: www-data
        mode: '0644'
      when: not config_www_created.stat.exists

    - name: Verifie si le repertoire des stats existe
      stat:
        path: "{{ awstats_stats }}"
      register: stat_created

    - name: Creation du repertoire des stats
      command:
        mkdir "{{ awstats_stats }}"
      when: not stat_created.stat.exists

    - name: Activation et lancement apache
      shell: |
        sudo systemctl start apache2
        sudo a2ensite awstats.conf
        sudo a2enmod cgid
        sudo systemctl enable apache2
        sudo systemctl restart apache2

    - name: Copie le fichier de configuration de rsyslog
      ansible.builtin.copy:
        src: "{{ awstats_local_rsyslog_config }}"
        dest: "/etc/rsyslog.conf"
        owner: root
        group: root
        mode: '0644'

    - name: Lancement rsyslog
        shell: |
          sudo systemctl start rsyslog
          sudo systemctl enable rsyslog

    - name: Verifie si le fichier configuration pour logrotate existe
      stat:
        path: "{{ awstats_log_rotate_conf }}"
      register: log_rotate

    - name: Copie le fichier de configuration de logrotate
      ansible.builtin.copy:
        src: "{{ awstats_local_log_rotate_config }}"
        dest: "{{ awstats_log_rotate_conf }}"
        owner: root
        group: root
        mode: '0644'
      when: not log_rotate.stat.exists

    - name: Relance logrotate
      command:
        sudo systemctl restart logrotate.service
      when: not log_rotate.stat.exists

Le fichier est assez volimineux ; il aurait pu être découpé en plusieurs tâches : pré-requis, installation des sources, configuration de rsyslog, configuration de logrotate...

Le fonctionnement du fichier est tout le temps le même : On vérifie l’existance d’un fichier ou répertoire et on exécute une commande si celui-ci n’existe pas.

Cela permet de relancer plusieurs fois le ‘Playbook’ et de continuer à l’endroit où il s’était arrêté (suite à une erreur ou à un abandon).

Configuration du Playbook

L’utilisation des rôles simplifie grandement les fichiers ‘Playbooks’. Je ne fais qu’ici, indiqué le nom du rôle répertoire contenant la tâche à lancer ‘awstats’. J’utilise ici ‘become’ et ‘become_method’ pour exécuter mes tâches avec les privilèges ‘sudo’. Ce fichier peut-être situer où vous voulez.

    ---
    - name: Install AWStats
    hosts: awstats
    become: yes
    become_method: sudo
    roles:
        - role: "config/awstats"

Remarque : J’utilise le fichier de configuration ‘hosts’ qui se trouve à la racine du répertoire ‘.ansible’. Pour la syntaxe de ce fichier, je vous renvoi à la documentation de Ansible.

Configuration des métadonnées pour le role ‘awstats’

Le fichier de configuration des ‘meta’ permet de faire le lien avec le fichier contenant les variables globales. Il se trouve dans config/awstats/meta/main.yml

Voici son contenu :

    dependencies:
    -  role: "config/commun"

Fichiers de configurations du serveur

Le fichier de configuration apache

Le ‘Playbook’ vas copier ce fichier local sur le serveur dans le répertoire /etc/apache2/sites-available/awstats.conf

Son contenu est le suivant :

    Listen 8080

    <VirtualHost *:8080>
        ServerName IP_SERVEUR:8080
        DocumentRoot /var/www/awstats/

        <Directory /var/www/awstats/>
            Options +FollowSymlinks
            AllowOverride All
            Require all granted
        </Directory>

        <IfModule mod_cgid.c>
            Define ENABLE_USR_LIB_CGI_BIN
        </IfModule>

        ScriptAlias /cgi-bin/ "/var/www/awstats/cgi-bin/"

        <Directory "/var/www/awstats/cgi-bin">
        AllowOverride None
        Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
        #SetHandler perl-script
        #PerlResponseHandler ModPerl::PerlRun
        AddHandler cgi-script .pl
        Require all granted
        </Directory>

        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined
    </VirtualHost>

Remarque : Il faudra remplacer ‘IP_SERVEUR’ par l’adresse IP de votre serveur ‘awstats’.

Le fichier de configuration de awstats

Le ‘Playbook’ vas copier ce fichier local sur le serveur dans le répertoire /var/wwww/awstats/cgi-bin/awstats.conf

Son contenu est le suivant :

    LogFile="/var/log/hugo/access.log"
    LogType=W
    LogFormat=1
    LogSeparator=" "
    SiteDomain="192.168.2.64:8080"
    DNSLookup=2
    DynamicDNSLookup=0
    DirData="/var/www/awstats/stats/"
    DirCgi="/cgi-bin"
    DirIcons="/icon"
    AllowToUpdateStatsFromBrowser=1
    AllowFullYearView=2
    EnableLockForUpdate=0
    DNSStaticCacheFile="dnscache.txt"
    DNSLastUpdateCacheFile="dnscachelastupdate.txt"
    SkipDNSLookupFor=""
    AllowAccessFromWebToAuthenticatedUsersOnly=0
    AllowAccessFromWebToFollowingAuthenticatedUsers=""
    AllowAccessFromWebToFollowingIPAddresses="192.168.2.5"
    CreateDirDataIfNotExists=0
    BuildHistoryFormat=text
    BuildReportFormat=html
    SaveDatabaseFilesWithPermissionsForEveryone=0
    PurgeLogFile=0
    ArchiveLogRecords=0
    KeepBackupOfHistoricFiles=0
    DefaultFile="index.php index.html"
    SkipHosts=""
    SkipUserAgents=""
    SkipFiles=""
    SkipReferrersBlackList=""
    OnlyHosts=""
    OnlyUserAgents=""
    OnlyUsers=""
    OnlyFiles=""
    NotPageList="css js class gif jpg jpeg png bmp ico rss xml swf eot woff woff2"
    ValidHTTPCodes="200 304"
    ValidSMTPCodes="1 250"
    TrapInfosForHTTPErrorCodes = "400 403 404"
    AuthenticatedUsersNotCaseSensitive=0
    URLNotCaseSensitive=0
    URLWithAnchor=0
    URLQuerySeparators="?;"
    URLWithQuery=0
    URLWithQueryWithOnlyFollowingParameters=""
    URLWithQueryWithoutFollowingParameters=""
    URLReferrerWithQuery=0
    WarningMessages=1
    ErrorMessages=""
    DebugMessages=0
    NbOfLinesForCorruptedLog=50
    WrapperScript=""
    DecodeUA=0
    MiscTrackerUrl="/js/awstats_misc_tracker.js"
    LevelForBrowsersDetection=2         # 0 disables Browsers detection.
                                        # 2 reduces AWStats speed by 2%
                                        # allphones reduces AWStats speed by 5%
    LevelForOSDetection=2               # 0 disables OS detection.
                                        # 2 reduces AWStats speed by 3%
    LevelForRefererAnalyze=2            # 0 disables Origin detection.
                                        # 2 reduces AWStats speed by 14%
    LevelForRobotsDetection=2           # 0 disables Robots detection.
                                        # 2 reduces AWStats speed by 2.5%
    LevelForSearchEnginesDetection=2    # 0 disables Search engines detection.
                                        # 2 reduces AWStats speed by 9%
    LevelForKeywordsDetection=2         # 0 disables Keyphrases/Keywords detection.
                                        # 2 reduces AWStats speed by 1%
    LevelForFileTypesDetection=2        # 0 disables File types detection.
                                        # 2 reduces AWStats speed by 1%
    LevelForWormsDetection=0            # 0 disables Worms detection.
                                        # 2 reduces AWStats speed by 15%
    UseFramesWhenCGI=1
    DetailedReportsOnNewWindows=1
    Expires=0
    MaxRowsInHTMLOutput=10000
    Lang="auto" # fr
    DirLang="./lang"
    ShowMenu=1
    ShowSummary=UVPHB
    ShowMonthStats=UVPHB
    ShowDaysOfMonthStats=VPHB
    ShowDaysOfWeekStats=PHB
    ShowHoursStats=PHB
    ShowDomainsStats=PHB
    ShowHostsStats=PHBL
    ShowAuthenticatedUsers=0
    ShowRobotsStats=HBL
    ShowWormsStats=0
    ShowEMailSenders=0
    ShowEMailReceivers=0
    ShowSessionsStats=1
    ShowPagesStats=PBEX
    ShowFileTypesStats=HB
    ShowFileSizesStats=0
    ShowDownloadsStats=HB
    ShowOSStats=1
    ShowBrowsersStats=1
    ShowScreenSizeStats=0
    ShowOriginStats=PH
    ShowKeyphrasesStats=1
    ShowKeywordsStats=1
    ShowMiscStats=a
    ShowHTTPErrorsStats=1
    ShowHTTPErrorsPageDetail=R
    ShowSMTPErrorsStats=0
    ShowClusterStats=0
    AddDataArrayMonthStats=1
    AddDataArrayShowDaysOfMonthStats=1
    AddDataArrayShowDaysOfWeekStats=1
    AddDataArrayShowHoursStats=1
    IncludeInternalLinksInOriginSection=0
    MaxNbOfDomain = 10
    MinHitDomain  = 1
    MaxNbOfHostsShown = 10
    MinHitHost    = 1
    MaxNbOfLoginShown = 10
    MinHitLogin   = 1
    MaxNbOfRobotShown = 10
    MinHitRobot   = 1
    MaxNbOfDownloadsShown = 10
    MinHitDownloads = 1
    MaxNbOfPageShown = 10
    MinHitFile    = 1
    MaxNbOfOsShown = 10
    MinHitOs      = 1
    MaxNbOfBrowsersShown = 10
    MinHitBrowser = 1
    MaxNbOfScreenSizesShown = 5
    MinHitScreenSize = 1
    MinHitWindowSize = 1
    MaxNbOfRefererShown = 10
    MinHitRefer   = 1
    MaxNbOfKeyphrasesShown = 10
    MinHitKeyphrase = 1
    MaxNbOfKeywordsShown = 10
    MinHitKeyword = 1
    MaxNbOfEMailsShown = 20
    MinHitEMail   = 1
    FirstDayOfWeek=1
    ShowFlagLinks=""
    ShowLinksOnUrl=1
    UseHTTPSLinkForUrl=""
    MaxLengthOfShownURL=64
    HTMLHeadSection=""
    HTMLEndSection=""
    MetaRobot=0
    Logo="awstats_logo6.png"
    LogoLink="http://www.awstats.org"
    BarWidth   = 260
    BarHeight  = 90
    StyleSheet=""
    color_Background="FFFFFF"               # Background color for main page (Default = "FFFFFF")
    color_TableBGTitle="CCCCDD"             # Background color for table title (Default = "CCCCDD")
    color_TableTitle="000000"               # Table title font color (Default = "000000")
    color_TableBG="CCCCDD"                  # Background color for table (Default = "CCCCDD")
    color_TableRowTitle="FFFFFF"    # Table row title font color (Default = "FFFFFF")
    color_TableBGRowTitle="ECECEC"  # Background color for row title (Default = "ECECEC")
    color_TableBorder="ECECEC"              # Table border color (Default = "ECECEC")
    color_text="000000"                             # Color of text (Default = "000000")
    color_textpercent="606060"              # Color of text for percent values (Default = "606060")
    color_titletext="000000"                # Color of text title within colored Title Rows (Default = "000000")
    color_weekend="EAEAEA"                  # Color for week-end days (Default = "EAEAEA")
    color_link="0011BB"                             # Color of HTML links (Default = "0011BB")
    color_hover="605040"                    # Color of HTML on-mouseover links (Default = "605040")
    color_u="FFAA66"                                # Background color for number of unique visitors (Default = "FFAA66")
    color_v="F4F090"                                # Background color for number of visites (Default = "F4F090")
    color_p="4477DD"                                # Background color for number of pages (Default = "4477DD")
    color_h="66DDEE"                                # Background color for number of hits (Default = "66DDEE")
    color_k="2EA495"                                # Background color for number of bytes (Default = "2EA495")
    color_s="8888DD"                                # Background color for number of search (Default = "8888DD")
    color_e="CEC2E8"                                # Background color for number of entry pages (Default = "CEC2E8")
    color_x="C1B2E2"                                # Background color for number of exit pages (Default = "C1B2E2")

    ExtraTrackedRowsLimit=500

Remarque : Il faudra adapter la variable ‘LogFile’ à votre fichier que vous souhaitez analyser.

Le fichier de configuration de rsyslog

Le ‘Playbook’ vas copier ce fichier local sur le serveur dans le répertoire /etc/rsyslog.conf

Son contenu est le suivant :

    module(load="imuxsock") # provides support for local system logging

    # provides UDP syslog reception
    module(load="imudp")
    input(type="imudp" port="514")

    # provides TCP syslog reception
    module(load="imtcp")
    input(type="imtcp" port="514")

    #
    # Set the default permissions for all log files.
    #
    $FileOwner root
    $FileGroup adm
    $FileCreateMode 0640
    $DirCreateMode 0755
    $Umask 0022

    #
    # Where to place spool and state files
    #
    $WorkDirectory /var/spool/rsyslog

    #
    # Log anything besides private authentication messages to a single log file
    #
    *.*;auth,authpriv.none          -/var/log/syslog

    :msg, contains, "pam_unix" stop
    :msg, contains, "pam_limits" stop


    $IncludeConfig /etc/rsyslog.d/*.conf

    #
    # Log commonly used facilities to their own log file
    #
    auth,authpriv.*                 /var/log/auth.log
    cron.*                          -/var/log/cron.log
    kern.*                          -/var/log/kern.log
    mail.*                          -/var/log/mail.log
    user.*                          -/var/log/user.log
    local7.*                        -/var/log/hugo.log

    #
    # Emergencies are sent to everybody logged in.
    #
    *.emerg                         :omusrmsg:*

Remarque : Il faudra adapter la variable ‘local7.*’ à votre fichier que vous souhaitez analyser.

Le fichier de configuration de logrotate

Le ‘Playbook’ vas copier ce fichier local sur le serveur dans le répertoire /etc/logrotate.d/hugo

Son contenu est le suivant :

    /var/log/hugo/*.log {
            daily
            missingok
            rotate 14
            compress
            delaycompress
            notifempty
            create 640 root www-data
            sharedscripts
            postrotate
                    /usr/lib/rsyslog/rsyslog-rotate
            endscript
    }

Remarque : Il faudra adapter la variable la premiere ligne à votre fichier que vous souhaitez analyser.

Lancement du ‘playbooks’

La commande à exécuter pour lancer le ‘Playbook’ est celle ci :

ansible-playbook --ask-become-pass -i hosts /repertoire_playbook/deploy_awstats.yml

Vous devez indiquer le chemin où se trouve votre fichier ‘Playbook’en remplacant ‘repertoire_playbook’. Ce fichier peut-être n’importe où, mais vous pouvez le mettre à la racine de votre dossier ‘.ansible’.

Remarque : J’utilise le fichier de configuration ‘hosts’ qui se trouve à la racine du répertoire ‘.ansible’. L’option ‘–ask-become-pass’ indique qu’il faut demander le mot de passe ‘sudo’ nécessaire à l’éxecution des tâches sur le serveur.

Si tout se passe bien, vous devriez avoir comme résultat :

Résultat de l’installation des sources

Consultation du service depuis votre LAN

AWStats est consultable via l’adresse : ip_du_serveur:8080

Si vous avez une erreur lors de la connexion au service ; c’est surement : un problème de droit sur des répertoires, un mauvais chemin dans la configuration… Le message affiché sera assez explicite.

Si le déploiement s’est bien exécuter, vous arriverez sur le tableau de bord principal :

Tableau de bord

Généré avec Hugo
Thème Stack conçu par Jimmy