Hokay… so…
I have a series of applications which are deployed to a single Tomcat application server. Let's call them appOne, appTwo and appFoo.
I am fronting these applications with an Apache reverse-proxy listening for appOne.mysite.com, appTwo.mysite.com and appFoo.mysite.com, and it effectively sends traffic where it needs to go using a pattern similar to the following:
<VirtualHost appOne.mysite.com:443>
[ ... ]
ProxyPass / http://serverOne.mysite.com:8080/appOne/
ProxyPass Reverse / http://serverOne.mysite.com:8080/appOne/
[ ... ]
</VirtualHost>
Because of how Tomcat works, each application is granted its own application context on serverOne.mysite.com:8080.
However, I don't want the user's to know they're hitting appOne, vs appFoo, so I want to hide it from the URL pattern reported by the browser.
Thus, a request for appOne.mysite.com should appear as appOne.mysite.com and not appOne.mysite.com/appOne/.
REJECTIONS
It's tempting to just rename the war file for an application to ROOT.war and deploy it because it automagically gets the root context. But in this case, each application should appear to be its own root context (isn't that part of why we use reverse-proxy configurations?).
It's also tempting to suggest that I turn off autoDeploy with Tomcat and provide custom context.xml files for each application… but that doesn't solve the issue of applications fighting over the root context designation and ends up being similar to renaming the war file just to get the context root.
It's also also tempting (see what I did there?) to suggest that I install multiple versions of Tomcat listening on unique ports… but this gets into complications with asking my organization to open firewall requests for different ports and I anticipate more and more of these applications popping up and sharing this Tomcat instance. (YAY for single threaded single points of failure!)
WHAT ABOUT…?
I have also considered that there could be programmatic methods I can recommend to the developers to make this more seamless, but I'm not as strong with Java DEV as I am with supporting it's infrastructure. I am open to suggestions here.
It's Possible…
It's entirely possible the answer is glaring me in the face and I don't see it because I've been staring at the problem for too long, or coming at it from the wrong angle.
Related
I have a website that I am trying to convert to a docker-compose solution.
Part of the website is a CMS (WordPress, specifically), and there are also a few Java web applications that are currently handled by tomcat.
The current approach is that I have an official WordPress container and an official Tomcat container. I load my custom content in the WordPress (via a MySQL container which is not really a part of this question) and the WAR files into tomcat.
So the problem is this:
Parts of the WordPress website have links to Java applications. Previously, some of these links were relative links as simple as /Application1 and the user would be able to access the Java application.
Now, since they are hosted in separate containers, I cannot do this because there is nothing named "Application1" in the WordPress container. I have modified the htaccess file for the WordPress container with a RewriteRules like this:
# Tomcat exposes port 8085
RewriteRule ^.*Application1/(.*)$ http://localhost:8085/Application1/$1 [R,L]
But this means that if the user clicks the link for Application1 in wordpress, their browser will then redirect them to localhost:8085 - which works fine if you run this set of containers locally, but does not work for remote users.
I could change localhost to the actual name of the server this will run on. But then it would need to be manually updated for every server this stack will run on, or reset to localhost for developers.
I could combine WordPress and Tomcat into a single container, but we were hoping to keep them separate so that when we need to upgrade, we just change the version of the container we are pulling rather than having to rebuild a custom container from scratch.
Is there a more seamless way to do this, so that the URL in the user's browser never changes? Is there way to get this working so that remote users won't even know that the different parts of the site are hosted in different containers?
Assuming you do docker-compose in development and also in production, you replace localhost with servicename of the corresponding upstream.
Lets say, you have 3 containers: httpd, fpm ( wordpress) and java ( tomcat ). You configure httpd, to redirect to fpm:9000 if its domain.tld/php and redirect to java:8086 if the request is domain.tld/Application1.
All you need to understand is, that the actual service-name you have in docker-compose is available as a hostname in the container ( all containers ) - so containers can reach themselfs using the service-name of the other container - that makes inter-container communication very easy and pre-configureable, without knowing the actual container IPs ( which will change during development / production and host migrations )
I think I figured it out: I should have been using a proxy instead of a RewriteRule.
This seems to get me what I want:
ProxyPass "/Application1" "http://my-tomcat-server:8080/Application1"
ProxyPassReverse "/Application1" "http://my-tomcat-server:8080/Application1"
We are using Apache Tomcat 7 for my web applications and we have decided to go on production stage.
So now is the time to think about how to secure the Tomcat and the machine. After reading "Apache tomcat security considerations" we decided to go on run tomcat process on dedicated user with minimum scenario.
From what I understand the best option is to configure it in a way that the running tomcat process has only read privilege to all the tomcat files.
I figured I would do it in this way:
I would create 2 users:
-tomcat_process - only for running tomcat
-admin - this is the one all the files belong to
tomcat_process will have access to conf directory, and also will be able to run scripts from tomcat/bin/
My main problem is that Tomcat needs to write to some files in $CATALINA_HOME/$CATALINA_BASE. I know I can change the location of logs and work directory and I thought I would point them to tomcat_process home dir (is this even a good idea?).
But I can't find any information if I can change the path to /conf/Catalina dir. Is it possible?
I would like to avoid adding write access to conf directory, as the whole configurations sits in there.
Or do you think that I should live those directories where their are and just add write privileges to them for tomcat_process?
I was wondering if you could please tell me if this is a correct approach or can I do it better?
I'm so confused with all those security guides which are telling me to restrict privileges but not telling how to do it :(
Keeping it simple I think is the key:
Create a new tomcat for each (set of) web application(s) with their own user.
Limit the tomcat resources to only the tomcat user. In linux you can use the chmod/chown command for this.
Place the tomcat behind a reverse proxy: Internet (https) <- external Firewall -> Apache Reverse Proxy <- Internal Firewall (block all unless whitelisted) --> Tomcat
Delete all standard webapps 'manager', 'root', 'docs'
Disable the shutdown command in server.xml
As for java web applications try to contain them in their own sandbox, meaning own database, own users.
To safe maintenance effort, you could run multiple instances using one tomcat binary and a single tomcat user.
http://www.openlogic.com/wazi/bid/188102/How-to-Run-Multiple-Instances-of-Tomcat-on-a-Single-Server
I am trying to use CloudBees PaaS (RUN#CloudBees) to consolidate essentially three different distinct uses under the same URL space:
root (/) main landing, marketing page
app (/app) java app running in CloudBees
blog (/blog) another java app running in cloudbees or possibly outside (example.wordpress.com)
If I was doing it myself in a datacenter or in AWS I would setup a reverse proxy (possibly like Varnish and configure reverse proxy to map the URL space as follows:
root (/): www.example.com/ --> CMS running as cloudbees app example-cms.cloudbees.net
app (/app) java app running in CloudBees www.example.com/app -> app.example.com
blog (/blog) similarly www.example.com/blog -> example.wordpress.com or exampleblog.cloudbees.net
How can I achieve the same with CloudBees. Can it be done? Is this too much to expect from a PaaS vendor?
An interesting problem, and a few solutions:
Use domains instead of paths (eg blog.example.com etc) - so you can use DNS to direct things
Build an app that essentially proxies traffic for you (this could run on cloudbees or elsewhere) - there are lots of ways to do this.
Use some routing/proxy service (like CloudFlare) which may let you set up routing rules (so it can proxy traffic).
My preference would always be for number 1 - DNS is a great way to do things like this.
You can with this approach have /blog similar Urls in your paas application, and have it do a 302 redirect to the real blog.example.com - that kind of gives you a bit of both.
There is one use case I am unable to solve so far with the Apache Jakarta (Tomcat) Connector load balancing feature.
I have one IIS site which has one Apache Tomcat Connector attached to it. I need to "forward" the traffic to a different Tomcat depending on the URI that is requested. It is pretty simple to do when you only have apps with a specific context (like /app1, /app2, etc). My problem is that I have one app (in one Tomcat) that is at / (ROOT) and one other app (in another Tomcat) that is at /app1.
I have tried the following config in uriworkermap.properties:
/*=loadBalancer1
/app1/*=loadBalancer2
But this doesn't work, because "loadBalancer1" takes all the traffic. "loadBalancer2" is being ignored, which make sense, since /app1/* matches /* (regexp wise).
I also tried adding a exclusion as so:
/*=loadBalancer1
!/app1/*=loadBalancer1
/app1/*=loadBalancer2
But that doesn't work either, because "loadBalancer1" is still taking all the traffic, but just ignoring that "/app1/*" URI pattern. "loadBalancer2" is simply ignored again.
Any suggestion, keeping in mind that I cannot have 2 IIS sites, nor can I move the app that is at / (ROOT) to a different context path in Tomcat?
Thank you
Edit:
Instead of using just one Apache Tomcat Connector, I use 1 connector for each Tomcat on the same IIS site.
uriworkermap.properties #1: for Tomcat with app at / (ROOT)
/*=wlb
!/app1/*=wlb
uriworkermap.proerties #2: for Tomcat with app at /app1
/app1/*=wlb
Connector #1 will ignore traffic on URI "/app1/*", but connector #2 will catch it (and vice versa).
Now I can set different VM options and memory allocation to my apps!
I am open to comments or better solution..
Does it work when you reverse it as such ?
/app1/*=loadBalancer2
/*=loadBalancer1
I have an existing web application which I have been building with an ant script and deploying as a .war file to Tomcat.
I am trying to add Drupal to my current technology stack to provide CMS and general UI-related functionality so that I don't have to write my html pages by hand and rather use templates.
During the installation of Drupal7, some of the instructions suggest that I go to this directory:
/etc/apache2/sites-available
and change the DocumentRoot to
/home/myuser/drupal/drupal7
If I make the docroot a basic directory on the file system, how will this impact how the application will work? In addition to Apache, I also have Tomcat server. My goal is to get them to all play nice together. How is this best accomplished?
If I make the docroot a basic directory on the filesystem
I'm not sure what you mean by this. There's no qualitative difference between /var/www and /home/mysuser/drupal/drupal7. The latter is longer and in the user's home directory, but assuming this user would be administering the service anyway that doesn't matter.
Next, the best way to make Tomcat and Apache get along is probably to run one of them on different subdomains. You could use the same domain, but that'd mean you had to run one of the daemons off a nonstandard port and that looks strange and might run into firewall trouble with some users.