2

Setup

I use Apache Tomcat 7 on an Arch linux distribution, and my webapps directory is located at /usr/share/tomcat7/webapps. In this directory one should create a directory, and put META-INF and WEB-INF directories in it with xml configuration files. Then this directory will be the main path of the webapp. Thus for example:

If /usr/share/tomcat7/webapps/foo/bar.html contains:

<!DOCTYPE html>
<html>
  <body>
    Hello world!
  </body>
</html>

Then http://localhost:8080/foo will show:

Hello world!

However, the goal is to have an external dynamic project (distributed by Netbeans in this case) as a webapp. So in that case I would like to locate my webapp here: /home/user/NetbeansProjects/foo/build/web/ (which contains bar.html).


I've come up with three possible approaches but none are working and I think I'm missing something.

Approach 1 (symlink)

I was thinking, let's put a symlink (symbolic link) in the webapps directory using this command:

$ ln -s /home/user/NetbeansProjects/foo/build/web /usr/share/tomcat7/webapps/foo

This seems like the most elegant approach, but Tomcat is not able to read the directory. Why not?


Approach 2 (mount --bind)

I read that you could also redirect one directory to another using mount --bind. So I tried to do this:

sudo mount --bind /usr/share/tomcat7/webapps/foo /home/user/NetbeansProjects/foo/build/web

Actually, this is the only solution that does work. Unfortunately, if I build the project again the mount will disappear. I have already tried to remount the directory after distributing the project using <exec/> in Ant, but this makes Linux crash for some weird reason. So this is not an option either. Also remounting after every clean-build seems not a clean approach. Mounting is also not really used for this kind of stuff, so I imagine the solution will not involve mounting.


Approach 3 (server.xml)

The last thing I want to do is to go againsts the recommendations of the Apache folks (see here). Which says:

It is NOT recommended to place elements directly in the server.xml file.

So what do I do, I take the default server.xml and add this Context-tag to the Host-tag:

<Context docBase="/home/user/NetbeansProjects/foo/build/web/" path="/foo"></Context>

However, if I restart the Tomcat service it fails to start. In the logfiles I read:

SEVERE: Error starting static Resources
java.lang.IllegalArgumentException: Document base /home/user/NetbeansProjects/foo/build/web does not exist or is not a readable directory

So, obviously this must be some kind of permission problem. Since I double checked for spelling errors the path must be correct. But I am not able to solve this, what I have done to grant tomcat7 (group: tomcat7) permission is:

chown -R tomcat7:tomcat7 /home/user/NetbeansProjects/foo/build/web
chmod -R 755 /home/user/NetbeansProjects/foo/build/web

But after restarting Tomcat, the same error occurs and Tomcat fails to start.


Which approach above is the most sensible, and what am I doing wrong that's preventing it from working?

5
  • 2
    You 'expect' for free ?
    – user9517
    Feb 11, 2014 at 17:56
  • 3
    In your question, I expect you to show the relevant configuration file.
    – Jenny D
    Feb 11, 2014 at 17:59
  • Which configuration file do you expect? All xml configuration files are defaults of the Tomcat 7 installation, except for the insertion of the <Context>-tag in to the Host-tag in server.xml for the second approach. And @lain, I was indicating that an answer to only one approach is sufficient to accept an answer, I'm sorry for my bad English/communication if you did not understand this ;)
    – Yeti
    Feb 11, 2014 at 18:46
  • 1
    For point one, tomcat.apache.org/tomcat-7.0-doc/config/context.html look over the allowLinking attribute.
    – Schrute
    Feb 13, 2014 at 20:26
  • Sorry, but allowLinking is for within a context. The symlink I am making here is the context directory itself, which may not be a symlink. (I tested this, and it did not work, as expected)
    – Yeti
    Feb 13, 2014 at 22:20

5 Answers 5

5

What @Schrute said in a comment (not an answer): Use option #1 (ln -s) and just allow linking in the Tomcat context.xml file. For Tomcat 7:

<?xml version="1.0" encoding="UTF-8"?>
<Context allowLinking="true">
...

Tomcat 8:

<Context>
    <Resources allowLinking="true"></Resources>
...

DO NOT DO THIS ON WINDOWS (or any other case-insensitive filesystem), as it will disable case sensitivity checks, allowing JSP source code disclosure, among other security problems. http://tomcat.apache.org/tomcat-8.0-doc/config/resources.html

4

The exact reason of why Tomcat cannot read the directories as in approach 1 and 3 are still unknown to me. However, it seems impossible for Tomcat to use any directory located under /home/user/... as a webapp, even if this means using symlinks to link to this location and setting correct permissions on the directories!

Although probably this is some kind of built-in protection. It is still strange because this behaviour is not listed in the Apache Tomcat documentation (correct me if I'm wrong).

The solution is therefore to use any other directory than /home/user/..., e.g. /usr/share/tomcat7/projects should work. But then again, it is best to set my Netbeans distribution output to the webapps directory directly as mentioned by another person (@user208992).

So in order to fix this problem, here is a list of instructions necessary to make Tomcat work with Netbeans using an external build/dist directory:

  1. Configure Netbeans to distribute the build and dist directories to a directory outside of /home/user/NetbeansProjects/project.

    Edit the following file: /home/user/NetbeansProjects/project/nbproject/project.properties, and change the lines:

    build.dir=build
    dist.dir=dist
    

    to

    build.dir=/srv/tomcat/project/build
    dist.dir=/srv/tomcat/project/dist
    

    Note that you can use any directory (other than /home/...) instead of /srv/tomcat/project

  2. Add a Context with a proper docBase to the Tomcat host.

    One way to do this is to edit the server.xml configuration file probably located in /etc/tomcat7/server.xml. Add a Context in the server.xml file:

    <Context docBase="/srv/tomcat/project/build/web/" path="/project"></Context>
    

    Make sure to place this within the <Host>-tag. Also you can add attributes to this tag when needed (reloadable, antiJARLocking etc). Or you could also place in xml file in CATALINA_HOME/engine(e.g. Catalina)/hostname(e.g. localhost)/project.xml, one of these approaches will be okay.

    I choose to point the docBase to .../build/web/ but you could also set this to .../dist/ if you want Tomcat to use the WAR-file.

  3. Make sure tomcat is in the same users-group as you are. To do this, e.g.:

    usermod --append --groups users tomcat7
    

    Note: Any common group you have with tomcat will suffice. This way Netbeans and Tomcat can both access the same directory.

  4. Fix ownership and permissions of the external project directory.

    sudo chown -R tomcat7:users /srv/tomcat/project
    sudo chmod -R 777 /srv/tomcat/project
    

    This assumes that you user are member of the group users, and tomcat7 is the name of tomcats user. You can check this incat /etc/passwd`.

    Note: Later on you can reduce the 777-permissions, but to make sure to let Tomcat have permissions you can start with the most accessible permissions.

  5. Do clean/build in Netbeans, and restart tomcat service. This will apply the changes from the previous steps.

I hope this will be helpful to somebody dealing with a similar situation; Tomcat and permissions can be really hard to debug imho.

3

Why don't you just let your netbeans build to your desired directory?

1
  • Exactly! A fourth approach, thank you, I completely overlooked this...
    – Yeti
    Feb 11, 2014 at 19:50
1

It might be worth trying setenforce 0 to disable selinux and retesting your above methods if selinux is enabled. If it works, re-enable selinux and start tracing down the permissions issues.


There are all kinds of security concerns here... (If you wanted to do something like this on Cent/Oracle/REHL... most sysadmins will tell you that you'll have to disable selinux or spend several hours chasing the audit log)

Long story short, there is nothing elegant about instantly publishing a build of software anywhere. The amount of problems that can potentially arise are things of nightmares (especially with java and tomcat lurking in the background).

You might do well to manually rsync from your development instance to a test instance. (IE Under Tomcat). If you want it to happen automatically.. You COULD add it to the build script.


Ps. I don't have time to look for supporting documentation... so: In my opinion it is neither best practice nor 'elegant' to combine the build and deploy stages of development (in almost all cases).

3
  • Probably copying/rsyncing the build directory to the webapp will be the only solution that will be guaranteed to work. However, you should note that the actual webapp will be rsynced to a web-server, and this webapp runs locally as a test-build for the local web-server, hence security is not an issue here.
    – Yeti
    Feb 11, 2014 at 18:41
  • Uhm, if I'm not mistaken, I do not have anything to do with SElinux. I use the Arch Linux distribution, which does not include that, so I should not have troubles with that right?
    – Yeti
    Feb 11, 2014 at 19:14
  • I don't know if you have the selinux enabled kernel or not. It's not my system. But, yes it is possible to have selinux and arch. Feb 11, 2014 at 19:16
0

I do agree with lVlint67 about separating Build and Deploy, but I also often work with php/html/javascript in a dev URL where the separation just seems to get in the way. I use the symlink method, but the catch is that the permissions must be set to allow the web server to read the destination of the symlink.

I use:

host:~# mkdir dev
host:~# chown me.www-data dev
host:~# chmod g+rwx dev
host:~# cd /var/www
host:~# ln -s ~/dev ./

For this to work, you have to be a member of the www-data group, and remember to keep your project files readable by group, and any files your app needs to write to will need to be writable by group.

This is all without SELinux, so your mileage may vary depending on your server config.

1
  • And this is exactly the problem, for both Approach 1 and 3. Even if I set chown to tomcat7:tomcat7 for the whole directory (recursively), and I set chmod 777, Tomcat still returns the same SEVERE error that it cannot read the directory.
    – Yeti
    Feb 11, 2014 at 19:12

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .