Mise en place d'un serveur de Home spécialisé systèmes Unix

From Deimos.fr / Bloc Notes Informatique
Jump to: navigation, search

1 Introduction

This article will show how to have a simultaneous dedicated profile on a lot of machine.

Here are the goals of this tutorial :

  • Account centralization with LDAP (this should already be done).
  • Each user will have his single personal unix profile on every unix servers.
  • The profile is the same everywhere with a share system.
  • They will have paths, aliases and environnements vars easier to set via a perl script.
  • The profile will be the same for every users (global environnemnt) instead of their personal adds.
  • Users on Windows will have their Unix profile on a share drive.
  • A special easy add environnement for Java is possible too.

2 Set global environnement

2.1 Global Profile

This file will be loaded everytime when a user will log on. You can add anything if you want it to be loaded. So here is the /etc/profile file :

Configuration File /etc/profile
# /etc/profile: system-wide .profile file for the Bourne shell (sh(1))
# and Bourne compatible shells (bash(1), ksh(1), ash(1), ...).
 
# If not running interactively, don't do anything
[ -z "$PS1" ] && return
 
# don't put duplicate lines in the history. See bash(1) for more options
export HISTCONTROL=ignoredups
 
# check the window size after each command and, if necessary,
# update the values of LINES and COLUMNS.
shopt -s checkwinsize
 
# make less more friendly for non-text input files, see lesspipe(1)
[ -x /usr/bin/lesspipe ] && eval "$(lesspipe)"
 
# Comment in the above and uncomment this below for a color prompt
PS1='\[\033[01;37m\][\[\033[01;32m\]`date +%D` \[\033[01;35m\]\t\[\033[01;37m\]] - \[\033[01;33m\][\w]\n\[\033[01;34m\]\u\[\033[01;31m\]@\[\033[01;34m\]\h\[\033[00m\] \[\033[01;31m\]\$\[\033[00;37m\] '
 
#######################################
# Default Variables and Environnement #
#######################################
 
# Uname system
export MYSYSTEM=`uname`
 
# Define Path
PATH="/usr/bin:/sbin:/usr/sbin:/usr/local/bin:/usr/local/sbin:/bin"
FULLPATH=$PATH 
 
# Linux
if [ $MYSYSTEM = "Linux" ] ; then
        CORE_NUMBER=`grep processor /proc/cpuinfo | wc | awk '{ print $1 }'`
        RAM_INFO=`free -m | grep "Mem:" | awk '{ print $2 "Mo / Free :", $3"Mo" }'`
fi
 
# Solaris
if [[ $MYSYSTEM = "SunOS" && -d /usr/openwin/bin/ ]] ; then
        PATH="$PATH:/usr/openwin/bin/:/usr/X11/bin:/opt/csw/bin"
        FULLPATH=$FULLPATH:$PATH
        CORE_NUMBER=`psrinfo | wc | awk '{ print $1 }'`
        RAM_MO=`echo "`vmstat | grep -v [a-z] | awk '{ print $5 }'`/1024" | bc`
        RAM_INFO=`echo `prtconf | grep "Memory size" | awk '{ print $3 }'`"Mo / Free : "$RAM_MO Mo`
fi
 
# Cygwin
if [ $MYSYSTEM = "CYGWIN*" ] ; then
        export TERM=cygwin
else
        export TERM=xterm-color
fi
 
export PATH
 
usernames=( $(cut -d: -f1 /etc/passwd) )
groups=( $(cut -d: -f1 /etc/group) )
 
case "$TERM" in
    xterm*|rxvt|linux|cygwin)
        ;;
    *)
        nocolor=yes
        ;;
esac
 
# Set locales
if [ $MYSYSTEM = "SunOS" ] ; then
        export LANGUAGE=fr_FR.ISO8859-15
        export LC_ALL=fr_FR.ISO8859-15
        export LANG=fr_FR.ISO8859-15
else
        export LANGUAGE=fr_FR@euro
        export LC_ALL=fr_FR@euro
        export LANG=fr_FR@euro
fi
 
export LESSCHARSET=latin9
export MINICOM="-c on"
export LESS="-S -g"
GCHECK=60
WATCHFMT="%n has %a %l from %M"
 
# CVS
export CVS_RSH=/usr/bin/ssh
export CVSROOT=:ext:user@host:/var/lib/cvs
 
# History
export HISTSIZE=5000
export HISTFILE=$HOME/.bash_history
export SAVEHIST=1
 
# Defaut editor
export EDITOR=vim
 
export LISTMAX=0
 
# Use most if possible
if [[ -x /usr/bin/most || -x /opt/local/bin/most ]] ; then
        export PAGER=most
else
        export PAGER=more
fi
 
#################
# Environnement #
#################
 
# Usefull alias
alias utar="tar -xvzf"
alias ..='cd ..'
alias ...='cd ../..'
alias uu='source /etc/profile &> /dev/null'
 
# ls 
if [ $MYSYSTEM = "Linux" ] ; then
        alias ls='ls --color=auto'
        alias l='ls --color=auto -lg'
        alias ll='ls --color=auto -lag | $PAGER'
fi
 
# Graphical User Informations
echo ""
echo "     You're connected has $USER on $HOSTNAME machine."
echo "     Connected users : `who -q | grep "=" | awk -F'=' '{ print $2 }'`"
echo "     Host OS : $MYSYSTEM - `uname -m`"
echo ""
echo "     Host CPU Core(s) : $CORE_NUMBER"
echo "     Host RAM : Total : $RAM_INFO"
 
# Personals mycompany users environnements
if [ -d ~/mycompany_bash ] ; then
        # Generate a correct file in /tmp dir
        for personal_env in `ls ~/mycompany_bash/` ; do 
                /etc/mycompany_skel/mycompany_alias_env.pl $personal_env
        done
        # Load the environnement 
        . /tmp/$USER"_genprofil" || echo "Error while trying to load your personnal environnement"
        rm -f /tmp/$USER"_genprofil"
else
        # Create the environnement for the new user
        cp -Rf /etc/skel/mycompany_bash ~/mycompany_bash
        chown -Rf $USER:Team ~/mycompany_bash
fi
 
if [ $JAVA_HOME ] ; then
        export PATH=$PATH_PERSO:$JAVA_HOME:$FULLPATH
else
        export PATH=$PATH_PERSO:$FULLPATH
fi
 
# enable programmable completion features (you don't need to enable
# this, if it's already enabled in /etc/bash.bashrc and /etc/profile
# sources /etc/bash.bashrc). 
if [ -f /etc/bash_completion ]; then
    . /etc/bash_completion
fi
 
umask 022

2.2 Easier env, alias and path Script

With this script, users could have a folder which called mycompany_bash with their own aliases, env or path. They only have to add a file in this folder which should contain :

  • alias : for an aliases file
  • env : for an environnement file
  • path : the path file

The syntax on all thoses files should be like :

Configuration File my_alias_file
ll = ls -l

For those who are using JAVA_HOME environnement, their is a special add which will autocreate the full path :

Configuration File my_env_file
JVM = 1.5.14

This will automatically create the good path to JVM.
Now you need the following script for this syntax to be taken in effect. Place it in /etc/global_skel/global_alias_env.pl :

Configuration File /etc/mycompany_skel/mycompny_alias_env.pl
#!/usr/bin/perl -w
# Made by Pierre Mavro
# Environnement charger for global users
 
use strict;
use Term::ANSIColor qw(:constants);
 
# Vars
my $file_to_analyse=$ARGV[0];
my $method;
my $mypath="";
my $counter=0;
 
# Function to check which type of file does it have to be treated
sub get_enval {
    open FILER, "<$ENV{HOME}/mycompany_bash/$file_to_analyse" or die "Couln't open file : $!\n";
    open FILEW, ">>/tmp/$ENV{USER}_genprofil" or die "Cannot create file on /tmp : $!";
    while (<FILER>) {
        if ($_ =~ /^(\w*)(\ |)\=(\ |)(.*)/) {
            # Keep contents
            my $first_arg=$1;
            my $second_arg=$4;
            # Alias
            if ($method eq "alias") {
                # Save alias in file
                print FILEW "alias $1='$4'\n";
            } elsif ($method eq "environnement") {
                # Env + AutoPATH the JVM for export
                if ($first_arg =~ /(jvm|jdk)/i) {
                    if ($second_arg =~ /(\d\.\d)\.(\d+)/) {
                        # Convert to the good format and save
                        printf FILEW "export JAVA_HOME='/test/jdk$1.0_%#02s'\n", $2; 
                    } else {
                        die "Your JDK PATH is in a bad format, please contact ITs";
                    }
                } else {
                    # Convert first arg to uppercase and save
                    print FILEW "export \U$first_arg\E=$second_arg\n";
                }
            } else {
                # If not reconnized die
                die "Problem on charging $method : $_\n";
            }
        } elsif ($method eq "path") {
            chomp $_; 
            unless ($_ =~ /^#/) {
                $mypath="$mypath:$_";
            }
        }
    }   
    if ($method eq "path") {
        print FILEW "PATH=$ENV{PATH}$mypath\n";
        print FILEW "PATH_PERSO=$mypath\n";
    }   
    close FILEW;
    close FILER;
}
 
sub check_problems {
    if ($file_to_analyse =~ /env/i) {
        $counter++;
    }
    if ($file_to_analyse =~ /alias/i) {
        $counter++;
    }
    if ($file_to_analyse =~ /path/i) {
        $counter++;
    }
    # If more than one path/env/alias... don't analyse this file
    if ($counter ne 1) {
        print CLEAR, RED, "\nWARNING : there is a problem with your $file_to_analyse file. Can't reconize what kind of file it is. Please rename this file correctly.\n", RESET;
    }
}
 
# Check for problems before starting
&check_problems;
# Alias
if ($file_to_analyse =~ /env/i) {
    $method="environnement";
    &get_enval;
# Environnement
} elsif ($file_to_analyse =~ /alias/i) {
    $method="alias";
    &get_enval;
# Path
} elsif ($file_to_analyse =~ /path/i) {
    $method="path";
    &get_enval;
}

Now add execution rights :

Command chmod
chmod 755 /etc/global_skel/global_alias_env.pl

2.3 Skel

In your /etc/skel, you need to made some change. First delete all the content :

Command rm
rm -Rf /etc/skel
mkdir /etc/skel

Next, we'll add some example files to help users to set their custom environnement. Create a folder and some files :

Command
mkdir /etc/skel/mycompany_bash
cd /etc/skel/mycompany_bash
touch alias env path

Now put this content in the alias file :

Configuration File /etc/skel/mycompany_bash/alias
## Personal Mycompany Aliases ##
#
# Purpose:
# This file contains your custom aliases,
# these little shorcuts that ease your life.
#
# Instructions:
# - If you want to put comments, add #
# - If you need to create aliases follow this example:
#         myalias = command
# - Your first argument should only be written in lowercase !
#
# Your alias file can be updated with the "uu" command or relog yourself.
#
# If you need other aliases files, simply create in your ~/mycompany_bash directory
# a new file containing "alias" in its name.
#
# Examples :
# javav = java -version
# ll = ls -lah
#

Next env file :

Configuration File /etc/skel/mycompany_bash/env
## Personal Mycompany Environnement ##
#
# Purpose:
# This file contains your custom environment variables
# that can be used in your scripts or aliases
#
# One usefull behavior is to specify some predefined tokens like:
#               JDK = 1.5.0_14
# that will automatically modify your path to add this JDK version and create JAVA_HOME variable.
#
# Instructions:
# - If you want to put comments, add #
# - If you need to create environment variables follow this example:
#               NAME_OF_THE_VARIABLE = value
# - Your first argument (NAME_OF_THE_VARIABLE here) sould only be written in uppercase !
#
# Your environment file can be updated with the "uu" command or relog yourself.
#
# If you need other environment files, simply create in your ~/mycompany_bash directory,
# a new file containing "env" in its name.
#
# Examples :
#   MY_ENV_TEST = test
#   MY_ENV_TEST2 = $MY_ENV_TEST/test2
#   DEV_DIR = ~/dev
#   JDK = 1.5.0_14
#

Then the path file :

Configuration File /etc/skel/mycompany_bash/path
## Personal Mycompany Path ##
#
# Purpose:
# This file contains your custom amendment to your PATH environment variable.
# It is used to add some directories in which binaries can be used everywhere
# without referencing the full path.
#
# Instructions :
# - If you want to put comments, add #
# - If you need to add directories to your path, just simply put them one by one (only one per line).
#
# Your path file can be updated with the "uu" command or relog yourself.
#
# If you need other path files, simply create in your ~/mycompany_bash directory
# a new file containing "path" in its name.
#
# Examples :
# /usr/bin
# /usr/sbin
#

3 Quotas

First, you should look at this documentation : Quotas Documentation.

For LDAP :
If you want to run a solution on FreeBSD, you can look at pam_quota. Unfortunatly, the guy who created this didn't had the time to do it for linux. So we must find another way and look at session scripts : Pam-script Documentation.

3.1 LDAP

If you have an LDAP, no way, we must take all users and create for each one of them a home directory and add quotas. That's why we will use PAM-script to do it automatically.

Once pam-script has been done, please add thoses lines to the "/etc/security/onsessionopen" file :

Configuration File /etc/security/onsessionopen
#!/bin/sh
# Made by Pierre Mavro
 
soft_limit=90M
hard_limit=100M
quota_folder=/home
 
userid=$1
service=$2
 
if [ $userid != "root" ] ; then
        if [ -x /usr/sbin/quotatool ] ; then
                /usr/sbin/quotatool -u $userid -bq $soft_limit -l $hard_limit $quota_folder
        else
                echo "/usr/sbin/quotatool doesn't exist. Can't set user quota"
                exit 1
        fi  
fi

You just need to set the 3 vars as you which and it will automatically be set to the next user connection.

3.2 PAM

If you have PAM and create your own users, just edit adduser.conf and configure this line :

Configuration File /etc/adduser.conf
# If QUOTAUSER is set, a default quota will be set from that user with
# `edquota -p QUOTAUSER newuser'
QUOTAUSER=""

Add in this line what you need for your quotas. Now create a new folder :

Command mkdir
mkdir -p /etc/scripts/

And add this script for already created users to have quotas sets :

Configuration File /etc/scripts/set_quotas.sh
#!/bin/sh
# Set quotas for every users
# Made by Pierre Mavro
 
# Set soft limit (in Mo)
soft_limit="90M"
# Set hard limit (in Mo)
hard_limit="100M"
# Quota directoy (where users are located)
home_users="/home"
# Quotatool binary
quotatool_bin="/usr/sbin/quotatool"
 
if [ -x $quotatool_bin ] ; then
    for username in `ls $home_users | grep -v aquota.user` ; do
        quotatool -u $username -bq $soft_limit -l $hard_limit $home_users
    done
else
    echo "Sorry but couldn't locate or can't execute $quotatool_bin"
    exit 1
fi

Adapt this as you wish and add rights now to be executable :

Command chmod
chmod 740 /etc/scripts/set_quotas.sh

Now add this to your crontab to be set every 5 minutes for example.

4 Share Servers Profiles

4.1 NFS

For a NFS server, read the NFS Server Documentation.

When installed, just configure the /etc/export file :

Configuration File /etc/export
/home (rw)

After that restart NFS services.

4.2 Samba

For Samba, please follow this : Samba and OpenLDAP Documentation.

5 Guests Servers

Now I need to set up a Linux server. When users will log into it, the Home profile should be automatically be mounted and unmounted at unlog.

5.1 Linux

We will use pam_mount to automate the NFS mount. Please follow this documentation.

Edit the /etc/security/pam_mount.conf file and configure what you need. Here we would like users to have nfs home share to be mounted from the server at logon. Add this line at the end of the file :

Configuration File /etc/security/pam_mount.conf
volume * nfs my_nfs_server /home/& ~ - - -

Edit the /etc/pam.d/ssh file and add those lines:

Configuration File /etc/pam.d/ssh
...
auth       required     pam_env.so envfile=/etc/default/locale
auth       required     pam_mount.so
@include   common-auth
...
@include   common-account
session    required     pam_mount.so
@include   common-session
...