Rendre public un dépôt gitMake public a git repository
Ce tutoriel explique comment
rendre public un dépôt git. Il existe deux méthodes pour cela : le rendre publique grâce à git-daemon
; (le protocole utilisé pour la connexion est alors ssh) ou bien le rendre public via un accès HTML. Comme mon serveur n’accepte que les connexions ssh authentifiées par une clé ssh, j’ai opté pour la seconde solution que je détaille dans cet article. Mon serveur est sous Ubuntu 12.04 et le serveur git est géré via gitolite.
Supposons que l’on souhaite rendre public le dépôt wnaetw
qui se trouve sur le serveur dans le répertoire /var/lib/gitolite/repositories/wnaetw
. La première chose à faire est de rendre utilisable le script post-update
qui se trouve dans ce répertoire :
cd /var/lib/gitolite/repositories/wnaetw
mv hooks/post-update.sample hooks/post-update
chmod a+x hooks/post-update
Ensuite, il faut donner des droits de lecture et exécution corrects aux dépôts pour permettre la lecture par le serveur apache :
chown -R gitolite:www-data /var/lib/gitolite/repositories
chmod g+x /var/lib/gitolite/repositories
chmod -R g+rx /var/lib/gitolite/repositories/wnaetw
Enfin, il reste à créer un hôte virtuel sur le serveur, par exemple http://gitolite.my-domain.org
, pointant vers /var/lib/gitolite/repositories
comme expliqué dans ce post.
Le dépôt wnaetw est alors accessible en lecture seule par
git clone http://git.nathalievialaneix.eu/wnaetw.git
Votre cloud personnel avec owncloudOwncloud, your own cloud
Owncloud est une solution de cloud personnel qui permet la synchronisation et le partage des fichiers, à la manière du célèbre Dropbox et qui permet également la gestion et la synchronisation des contacts et du calendrier (à la manière de google calendar, par exemple). L’installation sur serveur ubuntu est très simple…
Installation sur Ubuntu server
Pour installer owncloud (version 3.0 qui est loin d’être la dernière, malheureusement), il suffit de faire :
sudo apt-get install owncloud
Lors de l’installation, vous serez amené à configurer une base de données sur votre serveur MySQL et également un accès via le serveur apache pour accéder à l’application à l’url http://my-server.org/owncloud
. Connectez-vous simplement à l’URL pour accéder à l’application.
Quelques améliorations peuvent être apportées à l’installation de base :
-
il peut-être utile, pour des questions de clarté ou d’espace, de stocker les données dans un dossier particulier de
/home
: on peut créer un utilisateur owncloud à cette fin et installer les données dans/home/owncloud/data
. Ce paramètre est défini à l’installation ou bien dans le fichier/var/lib/owncloud/config
(option"datadirectory"
) ; -
on peut aussi configurer un hôte virtuel (comme décrit dans ce post) avec un accès ssh sécurisé (comme expliqué dans ce post). On accède alors à l’application avec une URL du type
https://mycloud.my-domain.org/
.
Synchroniser owncloud avec son ordinateur (Ubuntu)
Sous linux, j’accède à mes fichiers owncloud dans un répertoire dédié monté via le protocole WebDAV. Pour cela, j’ai procédé ainsi :
-
Installation et configuration des packages nécessaires :
sudo apt-get install davfs2 sudo dpkg-reconfigure davfs2
en choisissant l’option permettant d’utiliser l’utilisateur ordinaire à effectuer des montages WebDAV. On utilise ensuite l’utilisateur
me
à monter les répertoires WebDAV par :sudo usermod -aG davfs2 me
-
Renseigner le lien de montage : on va monter le répertoire distant dans le répertoire local
/home/me/owncloud
. Pour cela, on crée le répertoire correspondant et le répertoire de configuration de davfs2 :mkdir owncloud mkdir .davfs2
puis on crée un fichier contenant les informations de connexion à owncloud (nom d’utilisateur et mot de passe) :
nano .davfs2/secrets
qui contient
https://mycloud.my-domain.org/files/webdav.php /home/me/owncloud username password
puis on interdit la lecture de ce fichier :
chmod 400 .davfs2/secrets
(en fait, j’ai opté pour une solution encore plus sécurisée en créant le fichier secrets dans mon répertoire crypté ecryptfs et en faisant un lien symbolique vers ce fichier depuis
~/.davfs2/secrets
).Il ne reste qu’à renseigner les informations sur le montage dans le fichier des tables de montage en éditant en super-utilisateur le fichier
/etc/fstab
pour y insérer la ligne suivante :https://mycloud.my-domain.org/files/webdav.php /home/me/owncloud davfs user,rw,noauto 0 0
(on peut aussi mettre le montage à “auto” si on souhaite un montage automatique à la connexion). Le répertoire est alors monté (et synchronisé) et démonté par les commandes :
mount owncloud umount owncloud
Synchroniser owncloud avec Android
Les deux fonctionnalités qui m’intéressaient dans la synchronisation avec mon smartphone android était :
- synchronisation des contacts ;
- synchronisation des fichiers.
Synchronisation des fichiers
La synchronisation des fichiers se fait très simplement en téléchargeant et en installant l’application owncloud décrite sur cette page. On lance l’application sur le smartphone et on rentre les informations suivantes :
-
url du serveur :
https://mycloud.my-domain.org
; - nom d’utilisateur et mot de passe.
La synchronisation est alors faite automatiquement (si l’option est activée sur votre téléphone) ou via le menu de synchronisation du téléphone. Vous accédez aux fichiers de votre cloud.
Synchronisation des contacts
La synchronisation des contacts sur le smartphone est un peu plus délicate : l’application owncloud pour android ne la gère pas encore. J’ai donc utilisé carddav-sync beta (en version gratuite). On paramètre le compte en entrant :
-
l’url du carnet d’adresse :
https://mycloud.my-domain.org/apps/contacts/carddav.php/addressbooks/utilisateur/
; - nom d’utilisateur et mot de passe ;
- nom donné au compte sur le téléphone (par exemple « contacts-owncloud »).
On choisit alors un des carnets d’adresses disponible et il est importé sur le téléphone (et mis à jour chaque fois qu’on synchronise via le menu de synchronisation du téléphone). Par contre, les contacts du téléphone ne sont pas envoyé vers owncloud : il faut donc recréer son carnet d’adresse sur l’interface owncloud et le réimporter. On peut gérer les doublons en associant les comptes, ou en supprimant les anciennes données du téléphone.
Application shiny pour représenter votre réseau facebookA shiny app that displays your facebook network
Les scripts pour réaliser une interface web qui vous permet de représenter votre réseau facebook ? Voir l’article en anglais…
This post follows
this post and this other post that, respectively, described how to extract your friendship network from facebook and how to create a Graphical User Interface with R and the package shiny. In this, I simply provide a graphical user interface made with shiny to display your facebook network, with different options for representing the nodes (color, size…). The initial function commented on this post to collect information from your facebook network was re-written due to a recent change in the facebook graph API.
An example of how the application works is provided in this movie:
and the application may be testable here (where it is hosted by rstudio but I don’t know for sure how the application might react to many simultaneous connections because gathering the information from facebook takes several minutes at each time so you’d better be patient…).
Installing necessary packages
In this example, I am using several packages: shiny (now available on CRAN repositories), igraph to manipulate networks, RCurl and rjson to import and extract data from facebook and finally, RColorBrewer to better handle colors.
ui.R
The file ui.R
contains the description of the interface: mine is made of a left hand side panel where the options are set by the user (the access token pasted from the facebook graph API explorer and the meaning of node color, size and label) and of a right hand side panel where the results are displayed. The main functions used in this panel are:
-
textInput
to obtain a character string from the user (here, the facebook access token); -
selectInput
to make the user select an option from a list (here, meaning of the node color, size and label); -
checkboxInput
to display a checkbox clickable by the user; -
p
,br()
andHTML
for various HTML tags that can be used to print free text.
The interface also contains a right hand side panel, which is the main panel where the results are displayed. Thanks to the function conditionalPanel
, this panel displays a short user guide until an access token is given. Then, the main panel is divided into two tabs to organize outputs in a graphical part (where the network is displayed) and a statistical parts (where simple facts about the network are summarized). The outputs are displayed by using the functions plotOutput
(that displays a graph coming from the server.R
script and referenced by a name, here graph
) and tableOutput
(that displays a data frame coming from the server.R
script and referenced by a name, here stats
).
The full script is given below:
shinyUI(pageWithSidebar(
# Title of the application
headerPanel("Visualize your facebook network..."),
# Left hand side panel
sidebarPanel(
textInput("token",strong("Copy your access token here:"), ""),
selectInput("ncol", "Node color represents:",choices = c("community","betweenness","degree","uniform")),
selectInput("nsize", "Node size represents:",choices = c("degree","betweenness","uniform")),
selectInput("nname","Node names are:",choices=c("initials","facebook id","names")),
checkboxInput("lcc"," Only the largest connected component is displayed.",TRUE),
br(),
p(HTML("Script sources and explanations can be found on my blog.")),
p(HTML("This application is kindly provided by tuxette ;-)"))
),
# Right hand side panel
mainPanel(
# If the "token" text area is empty
conditionalPanel(
condition = "input.token == '' ",
h4("Basic user guide"),
p("To visualize your facebook network, please go to ", a("the facebook graph API Explorer", href="https://developers.facebook.com/tools/explorer")," to generate a token and copy it in the field on the left hand side panel. Do not forget to select proper permissions to give you access to your friends' data."),
p("You may wait for a long time for the first network to be displayed (until all your data are collected from facebook) and then you can change the way the network is displayed by selecting various options for the node colors, size and label.")
),
# If the "token" text area is not empty
conditionalPanel(
condition = "input.token != '' ",
tabsetPanel(
tabPanel("Chart",p(HTML("Wait a few minutes... I'm working...")),plotOutput("chart")),
tabPanel("Statistics",tableOutput("stats"))
)
)
)
))
server.R
The server.R
script reacts to changes in the input collected in the ui.R
(each referenced by a label and useable with input$LABEL
in the server.R
script) and calculates outputs that can be numerical values, data frames, charts… This script is made of 5 main functions:
-
facebook
is the generic function to collect information through the facebook graph API; -
fb.friends
usesfacebook
and the access token provided by the user to collect the list of friends. It is a reactive function, i.e., a function that reats to changes in the user’s input options; -
mainnet
usesfacebook
and the access token provided by the user to collect the information about mutual friendship among your friends. It is also a reactive function; -
output$chart
uses the two functionsfb.friends
andmainnet
to define a network and then to display it accordingly to the options specified by the user. It uses the package igraph to manipulate networks and it is also a reactive function that reacts to changes in the options chosen for representing the network; -
output$stats
uses the two functionsfb.friends
andmainnet
to define a network and then to calculate simple statistics. Mine told me that my network contains 150 friends among which Sabrina is the one who is the most connected.
The full script is given below:
library(RCurl)
library(rjson)
library(igraph)
library(RColorBrewer)
# Generic function that collects data from facebook through the facebook graph API
facebook = function( path = "me", access_token = token, options){
if( !missing(options) ){
options = sprintf( "?%s", paste( names(options), "=",
unlist(options), collapse = "&", sep = "" ) )
} else {
options = ""
}
data = getURL( sprintf(
"https://graph.facebook.com/%s%s/?access_token=%s", path, options,
access_token ) )
print(sprintf( "https://graph.facebook.com/%s%s/?access_token=%s",
path, options, access_token ))
fromJSON( data )
}
# Shiny ouputs calculation
shinyServer(function(input, output) {
# Collect information about the friends on facebook
fb.friends = reactive(function(){
friends = facebook( path="me/friends" , access_token=input$token)
friends.id = sapply(friends$data, function(x) x$id)
friends.name = sapply(friends$data, function(x) iconv(x$name,"UTF-8","ASCII//TRANSLIT"))
initials = function(x) paste(substr(x,3,3), collapse=" ")
friends.initial = sapply(strsplit(friends.name," "), initials)
list("initials"=friends.initial,"name"=friends.name,"fbid"=friends.id)
})
# Collect mutual friendship information on facebook
mainnet = reactive(function() {
the.friends = fb.friends()
N = length(the.friends$initials)
friendship.matrix = matrix(0,N,N)
for (i in 1:N) {
tmp = facebook( path=paste("me/mutualfriends", the.friends$fbid[i], sep="/") , access_token=input$token)
mutualfriends = sapply(tmp$data, function(x) x$id)
friendship.matrix[i,the.friends$fbid %in% mutualfriends] = 1
}
colnames(friendship.matrix) = the.friends$name
rownames(friendship.matrix) = the.friends$name
friendship.matrix
})
# Display the network
output$chart = reactivePlot(function() {
the.friends = fb.friends()
adj = mainnet()
the.full.graph = graph.adjacency(adj,mode="undirected")
V(the.full.graph)$initials = the.friends$initials
V(the.full.graph)$fbid = the.friends$fbid
if (input$lcc) {
the.clusters = clusters(the.full.graph)
the.graph = induced.subgraph(the.full.graph,which(the.clusters$membership==which.max(the.clusters$csize)))
} else {
the.graph = the.full.graph
}
if (input$ncol=="uniform") {
V(the.graph)$color = rep("seagreen",vcount(the.graph))
} else if (input$ncol=="degree") {
dclust = cut(degree(the.graph),9,label=F)
V(the.graph)$color = brewer.pal(9,"YlOrRd")[dclust]
} else if (input$ncol=="betweenness") {
bclust = cut(betweenness(the.graph),9,label=F)
V(the.graph)$color = brewer.pal(9,"YlOrRd")[bclust]
} else if (input$ncol=="community") {
all.cc = clusters(the.graph)
lcc = induced.subgraph(the.graph,which(all.cc$membership==which.max(all.cc$csize)))
clust = multilevel.community(lcc)
V(the.graph)$color = rep("yellow",vcount(the.graph))
V(the.graph)$color[match(clust$names,V(the.graph)$name)] = brewer.pal(12,"Paired")[clust$membership]
}
if (input$nsize=="degree") {
vsize = degree(the.graph)/max(degree(the.graph))*8
} else if (input$nsize=="betweenness") {
vsize = betweenness(the.graph)/max(betweenness(the.graph))*8
} else if (input$nsize=="uniform") {
vsize = rep(5,vcount(the.graph))
}
if (input$nname=="names") {
vname = V(the.graph)$name
} else if (input$nname=="facebook id") {
vname = V(the.graph)$fbid
} else if (input$nname=="initials") {
vname = V(the.graph)$initials
}
par(mar=rep(0,4))
set.seed(21121444)
plot(the.graph,layout=layout.auto,vertex.label=vname,vertex.label.font=1,vertex.label.color="black",vertex.color=V(the.graph)$color, vertex.frame.color=V(the.graph)$color,vertex.size=vsize)
})
# Calculate basic statistics
output$stats = reactiveTable(function() {
the.friends = fb.friends()
adj = mainnet()
the.full.graph = graph.adjacency(adj,mode="undirected")
deg = degree(the.full.graph)
the.bet = betweenness(the.full.graph)
data.frame(
Statistics = c("Number of friends", "Density", "Transitivity", "Average degree", "Max degree", "Average betweenness", "Max betweenness", "Best degree", "Best betweenness"),
Values = as.character(c(vcount(the.full.graph), paste(round(graph.density(the.full.graph)*100,0),"%",collapse=" "), paste(round(transitivity(the.full.graph)*100,0),"%",collapse=" "), round(mean(deg),1), max(deg), round(mean(the.bet),0), round(max(the.bet),0), names(which.max(deg)), names(which.max(the.bet)))),
stringsAsFactors=FALSE)
})
})
In case your would like to use and/or modify this application on your own computer (without the need to rely on the rstudio server), make sure all the necessary packages are installed, then copy/paste the two scripts ui.R
and server.R
in given directory (for instance, “DIR”) and, in R, run
library(shiny)
runApp("PATH2DIR/DIR")
where “PATH2DIR” is the path from your working directory to “DIR”.
Ubuntu serveur : configurer la langue et laisser sudo nous insulterUbuntu server: how to change language and how to allow sudo to insult you
Mon serveur était initialement configuré en français, avec des parties en anglais lorsque la traduction n’était pas disponible. Pour basculer entièrement en anglais (US), il faut d’abord régénérer les locales
sudo dpkg-reconfigure locales
puis éditer le fichier /etc/default/locales
et y insérer
LANG=en_US.UTF-8 LANGUAGE="en_US:en"
Un redémarrage du serveur permet de valider le changement.
En complément, vous pouvez permettre à sudo de vous faire de petites blagues lorsque vous vous trompez sur votre mot de passe en éditant le fichier /etc/sudoers
et en y modifiant la ligne
Defaults env_reset,insults
ce qui donne des remarques de ce type, lorsque l’on commet des erreurs de mots de passe :
Bien choisir son mot de passeHow to choose a secure password?
Un joli petit utilitaire pour générer des mots de passe robustes : pwgen (disponible dans les dépôts ubuntu). Il s’utilise comme suit :
pwgen -syn 10 5
vous générera 5 mots de passe de 10 caractères avec des majuscules, des minuscules, des chiffres, des symboles spéciaux et générés de manière totalement aléatoire. Plus d’information avec :
man pwgen