12.09.06
Posted in Java at 3:02 pm by skoobi
Jurgen - whom I totally agree with - has written a very nice post about Procedural-Object programmers.
Most people tend to forget that Designing/Coding a piece of software is not about getting things to work, but more importantly, about getting things to work in an elegant way.
And the biggest problem is that it is really hard to define what “elegant” means. My personal opinion is that the Open Source world is full of very good practices that help drive the decisions. Sure, some software are crap, but looking at how Spring, Compass, Hibernate or other Java developers solve technical problems is in any case very informative.
Another problem is about designing the domain. For that part, I urge anybody to look at “Domain Driven Design Quickly” or Eric Evan’s Domain Driven Design book.
Permalink
Posted in Unix / Linux, Web Development at 2:12 pm by skoobi
No matter who you are (Lambda internet/network user, Software Developer or System Administrator..), you are most-likely affected by the proliferation of accounts and passwords.
The problem
As an Internet user, you need to keep track of one account/password pair for each website you use. It is then necessary to choose between having the same password everywhere (the weakest part of the security chain is thus the weakest website…), or maintaining a potentially long document with all the website/password pairs…
As a Software developer, you need to keep track of all the system passwords (.htaccess passwords, database URL/passwords, accounts on the companies’ computers, and so on..).
Finally, as a System Administrator, you need to keep track of all the system’s passwords, which include each application’s password (MySQL root password, SYMPA password, LDAP Manager entry’s password, root passwords on each machine, Apache SSL certificates keys’s protection passwords….). Additionally each administrated (web) application has its own “admin” account with an associated password, and these applications’ configuration files often include passwords for other components of the system (database accounts/passwords, LDAP password, …). Even efforts such as using centralized LDAP authentication result in having some LDAP’s binding account in the configuration files…
Not only it is a mess to administrate, but it is also a very nice way to forget/mess up with permissions and this can result in weak systems that are easily hackable, because of the complexity.
The solutions
The solution to improve the end users experience would require the whole internet to switch to Single Sign On Solutions. Some vendors are pushing centralized SSO solutions, like Microsoft Passport, which is a pretty criticized solution, both technically and ideologically. Others are pushing open, distributed SSO solutions, like OpenID and LID.
Now that everybody is talking about the “Web 2.0″, it is time to think about improving the user’s experience and security, and this implies adopting one of these technologies in a large scale.
Concerning the Software developer’s and System Administrator’s problem, the problem is way more complex. Sure, the total number of accounts and passwords can be limited by using centralized authentication schemes for applications that support it - all should in a perfect world - (You can find more information about using a centralized LDAP repository for Linux/PAM on this page. If you go this way, you will have to find a good, secure distributed/network file system to share /home directories), but the way applications are currently designed does not open the door to an easy solution. Each application/server has a special “admin” mode that gives the user more permissions, and it is common practice to protect that account using a user-defined password.
So, I’d like to know if anyone has ever thought of something nice that could potentially change the world for system administrators and software developers ? One thing I can potentially think of would be a solution where specific roles would be defined and standardized (system administrator, database administrator, ….), and each application would work with the system to validate a set of credentials (and check that the given user has the required role) supplied by the user before giving the permissions. In other terms, this would be some kind of PAM with the addition that system groups would be standardized. And frankly, with the number of applications and needs, I do not really see this as a possible solution.
Another option would be to switch to certificates to authenticate the users. Coupled with well-defined discovery+ storage solutions, there could be some /etc/certificates folder (+ some mechanism to associate certificates with applications roles) containing public keys that applications would lookup in order to validate user credentials. This would imply that each application could somehow challenge the user who would have previously stored his private key on a system that would act as a mediator between each application and him. Humm.. well.. this doesn’t really sound as an easy solution to me…
Permalink
12.06.06
Posted in Java at 9:20 am by skoobi
Java HotSwap support is being improved with each release. More information about it can be found in Jonas Bonér and Geert Bevin posts.
The goal of hot swapping is to allow the JVM to take new versions of the classes into considerations without reloading the JVM/Application.
Jonas believes it is a bad idea, but I think he refers to the ability of HotSwap to be used for AOP-like byte code instrumentation. Jonas seems to be heavily involved in AOP framework development, so I am not going to contradict any of his claims.
However, I DO believe that HotSwap can be used to improve the developer’s experience. Consider a web application that contains 100 Hibernate classes and takes 20-30 seconds to load. Most of the development time is spent loading and reloading the context, for each slight change in the Controller and View layers. Baiscally, if you want to add some stuff in a web page, you have to
1] Modify the action (Struts/Webwork Action, Spring MVC Controller, or Tapestry Page) to load the data from a database
2] Modify the view (.jsp/.jtl for Spring/Struts/Webwork, .html for Tapestry)
3] Deploy the application (30 seconds)
4] Test it. See that there is an error.
5] Correct the error, re-déploy the application (another 30 seconds)
and so on…
So, one of the solution is to use Jetty to deploy the application (for instance, using the Maven2 Jetty6 Plugin). This allows for hot-redeployment of JSP pages, but does not take the new classes changes into consideration. Jetty + Tapestry 5 is an attractive option for developers since it allows for hot deployment of both the HTML and Java code. This is awesome, except that I believe it should not be the MVC Framework’s job to do all the gory details of detecting new classes, re-loading the new ones, and so on. It is necessary to have a generic solution that will benefit all frameworks without specific support from them.
And this solution is called Java HotSwap. I am looking forward to having IDE support for that, that will allow to forget, once for all, this costly change-build-redeploy process.
Permalink
Posted in Java, Web Development at 3:04 am by skoobi
With globalization, Character Set problems are becoming more and more frequent, and are sometimes even a headache, as Mark Pilgrim and Scott Balmos highlight it in their respective posts entitled Determining the Character encoding of a feed and String encodings - another thorn in interop. Character sets are no more than a simple mapping between characters and numbers, and some encodings, such as Unicode UTF-8 tackle the interoperability issue correctly.
So, the real solution to all these problems would be to leverage UTF-8 as the default encoding for every application. If communication is necessary with a legacy system that does not support UTF-8, then whatever ISOxxx encoding is acceptable in a small wrapper that translates the stream to a UTF-8 one. In order to accomplish this :
- Make sure the default locale on all your systems are UTF-8. Recent linux distributions like Ubuntu luckily default to that.
- When writing or reading anything to a stream, Java (and I believe other languages too) defaults to the default encoding on the system. Do NOT trust this value, and make sure to only use the Reader/Writer constructors (example: OutputStreamWriter provides a few constructors that take the Charset. Use these constructors at ANY COST, and possibly write Jalopy rules that prevent the use of the default ones).
From a more general point of view, it would be desirable to have UTF-8 everywhere : Domain Name System (which stil uses ASCII), SMTP (which reverts to ugly hacks to allow people to write non-ASCII characters), etc…
The internet is an international place, and as such, should not be ASCII-centric. This means that if the standardization organisms (IETF, ..) do not realize this, we are going to see more and more forking such as China’s reform to its DNS, which is obviously a bad thing for the community since it creates more interoperability issues.
Permalink
11.28.06
Posted in Uncategorized, Java at 7:17 am by skoobi
Dalibor Topic has been interviewed (post here) concerning the recent announcement of Sun to make Java GPL, its implication on the Kaffe project.
As far as I am concerned, I strongly believe that Open Sourcing Java will open the door to more innovation and wider adoption around/of this technology. When it comes to high-level languages, the only truly Free (Libre) option on the linux/*NIX desktop was to use Mono/C# (more and more GNOME applications are written in C#). Adding more competition by releasing Java Open source will most probably lead to better, easier to maintain applications.
Another important point about the GPL’ing of Java is that Java itself will benefit from the change. Look at GCJ, for instance, which tries to get rid of the JVM and directly compile java to machine Code. It is yet to prove whether this approach would actually make Java faster, but in any case, it would help to better integrate Java with the unix-way of doing things, instead of having Java on one side, and the whole OS on the other side. Few to no efforts have actually been done in order to mix high-level languages with the system. GCJ is currently struggling to implement both the language and classlib aspects of Java. Once the classlib will be released as Open Source software, GCJ developpers will be able to concentrate on the compiler itself, and on the integration of Java with C/C++ code, which will be an incentive for the people who don’t like JVMs to use Java (after all, Java will just be a simpler C++ that provides a decent library by default).
Permalink
11.27.06
Posted in Java, Web Development at 12:20 am by skoobi
DWR is an Open Source Java library that allows to write AJAX-enabled Web Sites. Since the “AJAX” term is used to to describe pretty much anything from rich Web User Interfaces to auto-completing combo boxes to asynchronous communication between the web client and the server, here is a more technical introduction that explains what DWR allows to do :
DWR is basically a Remote Method Invocation framework that allows to “export” server-side Java Objects to the javascript-enabled web client thanks to a transparent communication layer that dynamically (at runtime) generates the client stubs. So, in other terms, You have server side Java methods that you want to run from the client. DWR takes these classes/methods and provides you with a javascript file (generated on-the-fly) that provides javascript classes/methods that once called, will handle all the method calls, marshalling/unmarshalling, etc..
DWR does not provide any UI-abstraction layer. In order to create nifty graphics, you have to complement it with another framework like Dojo toolkit, or Script.aculo.us
Since the official documentation isn’t particularly clear on how to get DWR to work with Spring-managed beans and Java5 Annotations, here is a mini-HOWTO that completes it. (Anyone is free to use this HOWTO under any OSI-approved Open Source license). Nothing is easier to understand than a simple example, so we are going to create a Client Side Logger API that logs the events on the server-side thanks to Log4j. (A real-world example should use some abstraction layer like Commons-Logging , and should result in the creation of a backend to some of the popular Javascript logging frameworks, like Log4Javascript, instead of reinventing yet another logging API).
As a sidenote, DWR is part of the typical Bleeding Edge Web-Framework Stack that I wrote about in a previous post. Surely, not everybody uses this Stack, but it gives an idea of what the current trend in the Java world is. The current java world is full of innovation. Every 2 days, a new framework arrives on the scene, and beginners are more and more afraid of the overall complexity of the platform (if we can call this a platform, because it more looks like a set of unrelated tools that people struggle to use together, in opposition to Microsoft .Net’s stack that we can safely call a “solution” because of the tight integration between the components). Innovation is doublessly a very good thing, and nothing should prevent innovation from happening. However, I believe it is also very important to document the best practices and tools and try to gather the community around a limited set of paradigms and frameworks. It doesn’t make sense to have a different framework for each programmer in this world. And in my humble opinion, using such an RMI-like system for communicating between Java classes and Javascript is definitely one of the best and efficient (from the developers viewpoint) practices around.
Java class
The first step is to create the annotated Java5 class that will be exported to the Javascript client. All exported methods must be annotated thanks to the @RemoteMethod annotation, and the @Create annotation is used at the class level to tell DWR that the class is instantiated using the Spring Framework. The beanName parameter must reflect the name of the bean in Spring’s application context file.
@Create(creator = SpringCreator.class, creatorParams = { @Param(name = “beanName”, value = “clientSideLogger”) })
public class ClientSideLogger {
public static Logger logger = Logger.getLogger(ClientSideLogger.class);
/**
* @param arg0
* @see org.apache.log4j.Category#debug(java.lang.Object)
*/
@RemoteMethod
public void debug(String arg0) {
logger.debug(arg0);
}
/**
* @param arg0
* @see org.apache.log4j.Category#error(java.lang.Object)
*/
@RemoteMethod
public void error(String arg0) {
logger.error(arg0);
}
/**
* @param arg0
* @see org.apache.log4j.Category#fatal(java.lang.Object)
*/
@RemoteMethod
public void fatal(String arg0) {
logger.fatal(arg0);
}
/**
* @param arg0
* @see org.apache.log4j.Category#info(java.lang.Object)
*/
@RemoteMethod
public void info(String arg0) {
logger.info(arg0);
}
/**
* @param arg0
* @see org.apache.log4j.Category#warn(java.lang.Object)
*/
@RemoteMethod
public void warn(String arg0) {
logger.warn(arg0);
}
Spring Configuration
In order to instantiate the ClientSideLogger class with Spring, we can create the following dwr.xml file, that is going to create a “clientSideLogger” singleton :
<?xml version=”1.0″ encoding=”UTF-8″?>
<beans xmlns=”http://www.springframework.org/schema/beans” xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”
xmlns:aop=”http://www.springframework.org/schema/aop” xmlns:tx=”http://www.springframework.org/schema/tx”
xsi:schemaLocation=”http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd”>
<bean id=”clientSideLogger” class=”fr.cvf.vodoo.ihm.portal.dwr.ClientSideLogger” />
</beans>
Web.xml glue
The next step is to write the usual glue (setup the DWR/Spring servlet, etc…).
In your web.xml, you can add :
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/dwr.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!– DWR servlet , that should list all annotated classes–>
<servlet>
<servlet-name>dwr-invoker</servlet-name>
<display-name>DWR Servlet</display-name>
<servlet-class>org.directwebremoting.servlet.DwrServlet</servlet-class>
<init-param>
<param-name>debug</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>classes</param-name>
<param-value>
package.ClientSideLogger
</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>dwr-invoker</servlet-name>
<url-pattern>/dwr/*</url-pattern>
</servlet-mapping>
Javascript Code
The final step is to use the logging using the automagically generated javascript API.
First, make sure the following javascript files are included :
<script type=’text/javascript’ xsrc=’/dwr/interface/ClientSideLogger.js’>
</script>
<script type=’text/javascript’ xsrc=’/dwr/engine.js’></script>
<script type=’text/javascript’ xsrc=’/dwr/util.js’></script>
And you can use the API :
ClientSideLogger.error(”error message”);
That’s all you have to do !
Permalink
11.26.06
Posted in Unix / Linux, Tips and Documentation at 10:24 am by skoobi
Debian/Ubuntu sympa packages rely on apache1, so one may have problems running sympa on Ubuntu Edgy, for instance.
This simple HOWTO explains how to configure Sympa and WWS to run with Apache2 and FastCGI. FastCGI is used instead of CGI because of the performance impact it has. (Basically, CGI forks a new instance of the CGI script wheareas a FastCGI-enabled script runs as a daemon to handle requests, much like a decent system like Java Servlet API.)
Installation
Install the sympa package, and copy the installed apache1 configuration files to apache2 folder
# apt-get install sympa libapache2-mod-fastcgi
# ln -s /etc/sympa/httpd.conf-fcgi /etc/apache2/conf.d/sympa-fcgi
# dpkg-reconfigure -plow sympa
A wizzard will come up, make sure to :
- Use a database if you want to use WWS
- Select “Other” when asked what type of web server you are running
- Tell the wizzard that you want FastCGI enabled
Once this is done, check the /etc/sympa/wwsympa.conf file, and make sure
use_fast_cgi is set to 1
and the last step is to restart apache :
/etc/init.d/apache2 restart
Now, my personal thoughts about mailing-list systems. My impression is that there is no perfect Open Source mailing-list system (however, there are several ones that “do the job”). The characteristics of a good mailing-list system would be, to my opinion :
- Be entirely configurable through a Web UI. Sympa does a pretty good job at this, since most of the settings are tweakable from WWS. However, the UI is pretty ugly (sure, one can tweak the templates, but…)
- Would provide a Mailing-List system as well as a Web forum. To make it simple, something like Google Groups, that also allows to post (and subscribe/unsubscribe orders) via email. It is then up to each subscriber to choose between email and Web.
- Re-uses a well-known templating system ( Smarty in the PHP world, or Freemarker in the Java world, …). Why re-inventing yet another templating language if very good ones already exist ? Having to learn a templating language per web-application is pretty much cumbersome.
- Be extensible : It should provide a decent plugin system, that people can use to provide additional modules without touching a single line of the current base code. Requiring the modification of a 9980-line (cat /usr/lib/cgi-bin/sympa/wwsympa.fcgi | wc -l) perl script is, In my humble opinion, very bad practice. This implies coding against interfaces, and using some kind of IoC framework like the Spring Framework.
- Would be independant of the persistence layer, through the use of a sophisticated persistence engine such as Hibernate. Anyone can then configure it to use his preferred database engine
- Authentication would also be extensible. A security framework such as Acegi could be used so that anyone can easily have the mailing list system authenticate the users against the configured authentication backend. (be it database, system/PAM, Single-Sign-On, etc..). It doesn’t make sense to re-implement every authentication backend in every webapp, since some frameworks already do the job.
Permalink
Posted in Unix / Linux, Tips and Documentation at 8:11 am by skoobi
Prerequisite : You have Xen running correctly for less than 3 virtual interfaces. This HOWTO explains how to get it to work on Ubuntu Edgy.
Xen does not support using more than 3 virtual interfaces on the guest machines (the so-called DomU). It is stated in the Xen FAQ, and attempting to use more results in what Ernie Fontes experienced in this post.
The usual trick for having more interfaces in a stand-alone system is to use IP Aliasing. Ubuntu Linux, among others, support IP Aliasing without any problem. However, IP Aliasing seems not to work (according to my tests) for a Xen DomU.
For some reason that I cannot explain nor understand, there is still a way to use more than 3 virtual interfaces in a Xen DomU by using the offical Xen way of adding interfaces, and by using IP Aliasing on top of that. It is weird, but it works :
- using Xen virtual interfaces is limited to 3 interfaces.
- using IP aliasing interfaces makes interfaces that are not pingable from the outside
- BUT using exactly 3 Xen virtual interfaces, and adding more interfaces thanks to IP Aliasing works beautifully….
Here is a quick HOWTO explaining this procedure :
Xen Configuration
Add 3 interfaces for the DomU (you might replace xenbr1 by xenbr0 if your bridge name is the standard one) :
vif = [ ‘bridge=xenbr1′,’bridge=xenbr1′,’bridge=xenbr1′ ]
And you can create your domain using the usual xm create command.
xm create config.cfg
xm console
DomU Network configuration
You can now configure your domain interfaces and the aliases. For the sake of giving a complete example, here is how to achieve that under Debian/Ubuntu :
Let’s say that we want to configure the 216.240.153.78, 216.240.138.247, 216.240.146.76 IPs for, respectively, eth0, eth1 and eth2, and 216.240.134.6 as well as 216.240.128.182 for the 2 aliases eth0:0 and eth0:1.
/etc/network/interfaces
auto eth0
iface eth0 inet static
address 216.240.153.78
netmask 255.255.255.0
gateway 216.240.153.1
auto eth1
iface eth1 inet static
address 216.240.138.247
netmask 255.255.255.0
gateway 216.240.138.1
auto eth2
iface eth2 inet static
address 216.240.146.76
netmask 255.255.255.0
gateway 216.240.146.1
auto eth0:0
iface eth0:0 inet static
address 216.240.134.6
netmask 255.255.255.0
gateway 216.240.134.1
auto eth0:1
iface eth0:1 inet static
address 216.240.128.182
netmask 255.255.255.0
gateway 216.240.128.1
You can now tell the system to reconfigure the network (/etc/init.d/networking restart), and if it still doesn’t work (especially for the aliases), you can restart the DomU (xm reboot domU-name).
Now, if someone has an idea of why this tip works, I am really really interested to know. Because right now, it looks like magical stuff that I’m not even sure of how I discovered
Permalink
11.22.06
Posted in Unix / Linux, Tips and Documentation at 9:12 am by skoobi
If you have recently migrated your AWstats to a different Architecture (Pentium4 to AMD64, for instance), awstats may report you the following error :
Warning: Error while retrieving hashfile: Byte order is not compatible at ../../lib/Storable.pm (autosplit into ../../lib/auto/Storable/_retrieve.al) line 331, at (eval
line 1
This is caused by the fact that awstats/perl caches DNS Entries in a machine-dependant way. Others have experienced the same problems, like on this forum.
The solution is actually quick. Let’s say your stats are in /stats, you can do :
find /stats -name ‘*.hash’ -exec rm {} \;
Permalink
Posted in Unix / Linux, Tips and Documentation at 9:07 am by skoobi
Here is a simple HOWTO explaining how to configure AWstats to analyze Apache2 logs, and provide detailed statistics, under Ubuntu Edgy Eft. This should also work for other Ubuntu versions, as well as any Debian derivative.
Apache
The first step is to activate Logging in Apache, so that Awstats has something to analyze. For instance, you can add something similar in your VirtualHost configuration :
ErrorLog /var/log/apache2/sirika.com-error.log
CustomLog /var/log/apache2/sirika.com-access.log combined
Another important thing is to configure a few things for awstats in apache, like where the icons are, and more importantly, to activate CGI-scripts (since AWstats is written in perl…) . This can be done thanks to the following /etc/apache2/conf/awstats.conf :
# This provides worldwide access to everything below the directory
# Security concerns:
# * Raw log processing data is accessible too for everyone
# * The directory is by default writable by the httpd daemon, so if
# any PHP, CGI or other script can be tricked into copying or
# symlinking stuff here, you have a looking glass into your server,
# and if stuff can be uploaded to here, you have a public warez site!
Options None
AllowOverride None
Order allow,deny
Allow from all
# This provides worldwide access to everything below the directory
# Security concerns: none known
Options None
AllowOverride None
Order allow,deny
Allow from all
# This provides worldwide access to everything in the directory
# Security concerns: none known
Alias /awstats-icon/ /usr/share/awstats/icon/
# This (hopefully) enables _all_ CGI scripts in the default directory
# Security concerns: Are you sure _all_ CGI scripts are safe?
ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
Awstats
The next step is to install awstats, with all the necessary perl modules.. Using several optional modules implies that you have installed them. liburi-perl is useful if you use the “decodeutfkeys” module, even though it is NOT listed as recommended or suggested in the awstats package.
sudo apt-get install awstats libnet-dns-perl libnet-ip-perl libgeo-ipfree-perl liburi-perl libnet-xwhois-perl
Once this is working, it is now necessary to configure awstats, to tell it which logs it should monitor, and where it should write its working files (stats). This is done by creating a file /etc/awstats/awstats.website.conf (replace website by your apache2 virtual host name, for instance, and do NOT forget the .conf !).
sudo cp /etc/awstats/awstats.conf /etc/awstats/awstats.website.conf
Editing this file should be pretty straightforward, since it is well commented. In particular, pay attention to the following entries
LogFile=”/var/log/apache2/sirika.com-access.log”
SiteDomain=”sirika.com”
HostAliases=”www.sirika.com”
DirData=”/srv/data/stats/sirika.com”
LogFile should point to the log file configured in Apache2.
SiteDomain is the main domain name, as configured in Apache2.
HostAliases should list ALL the aliases listed in Apache2’s VirtualHost configuration. Usually, you will want the same domain prefixed with www, (or without the www prefix if is it already specified in the main domain name). This is really annoying, error-prone and not having a global definition of a “virtual host” on the system is one of the issues I pointed in “10 things that still suck under linux“. Virtual hosts and aliases should be defined once, globally. Every single concept/thing should be repeated/configured once, and only once, on a perfect system. Anyways…
DirData should point to an empty directory, whose content will be managed by Awstats.
Cron
Everything is now configured. On a perfect system, the setup would stop now. Awstats could be automagically notified for every change in the logs (awstats could register to a so-called “http access event”, and its internal behaviour could define its policy for updating the stats (update synchronously, update asynchronously when the system is idle, etc..). This is one of the things I pointed out in “10 things that still suck under linux“. However, we’re not there yet, so, we need to run the script every day to update the stats. (yeah, that’s the reality today..)
So, this can be done thanks to the following /etc/cron.daily/awstats (do not forget to chmod +x /etc/cron.daily/awstats after creating it) :
#!/bin/sh
/usr/share/doc/awstats/examples/awstats_updateall.pl -awstatsprog=/usr/lib/cgi-bin/awstats.pl now > /dev/null
This will update all the statistics for all the hosts defined in /etc/awstats/*, on a daily basis. Yes, it’s not as beautiful as having a full-featured event-system for which every application could attach to events generated by others, but it has the merits of working…
Logrotate
What happens when your apache logs get rotated (and possibly gzipped, etc) by logrotate (apt-cache show logrotate for more information), and awstats still hasn’t analyzed the end of the logs that is about to be rotated ?
To avoid this situation, it is necessary to tell logrotate to launch awstats BEFORE rotating the logs. This can be done by adding the following lines to /etc/logrotate.d/apache2 :
prerotate
/etc/cron.daily/awstats
endscript
Permissions
And of course, permissions must be tweaked :
- Since Awstats runs as the web users for viewing stats (CGI-script), the web user needs read access to /srv/data/stats/*
- Additionnally, you may want to provide the “update now” button on your website stats. So, the web user also needs write access to /srv/data/stats/*
- Finally, awstats needs access to the apache2 logs to create the stats. This is not a problem when it is run from a cron script, since it is run as root. But, in the case of “update now”, it runs as the web server, so the web server needs read access to its logs. (the default permissions are 660 with root:adm), so www-data doesn’t have access to its logs
The problem with traditional permissions is that there is no decent way of specifying default permissions. So, we are going to use ACLs for that. You can find more information about them here (Using POSIX ACLs to complement traditional Linux permissions). So, this gives, for instance :
# read write execute access for web user to the stats directories
find /srv/data/stats -type d -exec setfacl -m “g:www-data:rwx” {} \;
# read write execute access for FUTURE stats files for the web users
find /srv/data/stats -type d -exec setfacl -d -m “g:www-data:rwx” {} \;
# read write access to the stats files for the web user
find /srv/data/stats -type f -exec setfacl -d -m “g:www-data:rw-” {} \;
# read only access to the logs directory for the web user
find /var/log/apache2 -type d -exec setfacl -m “g:www-data:r-x” {} \;
# read only access to the logs for the web user, for future files
find /var/log/apache2 -type d -exec setfacl -d -m “g:www-data:r-x” {} \;
# read only access to the apache2 logs for the web user
find /var/log/apache2 -type f -exec setfacl -m “g:www-data:r–” {} \;
And it should work.. The last thing would be to protect access to your logs, if you don’t want your users to see them. This can be done using a .htaccess file, and there are plenty of tutorials on the web that explain how to achieve that.
Permalink
« Previous entries · Next entries »