Interfacing Docker containers apps with an existing Apache web server - apache

I am fairly new to Docker and I have some trouble to understand how to make my "contained" apps accessible from the internet.
[my current configuration] two web sites (in /var/www/html) + standard Apache + some tweeking I would like to be applied to everything new I deploy (headers CSP based rewriting, SSL certificate renewal with Certbot, etc etc). I am fairly happy with my current conf.
[my two apps] Both are standalone applications (only requiring a db).
-official wordpress image. (-> new domain name)
-a django based app packed with a gunicorn server based on this tutorial (-> subdomain of an existing domain )
[the issue] If I bind both apps on, say, ports 8080 and 8000, browsers wont be able to reach it, for DNS servers do not handle ports (from what I understood, correct me if I am wrong). If I bind then on standard ports, I'll have a conflict with my existing Apache.
How would you deal with it? Can I redirect to containers' internal ip with a mod_proxy of some kind? Is there a cleaner-easier-safer way to do it?
<VirtualHost *:443>
ServerName sub.mydomain.io
Redirect "/" "http://172.17.0.2/"
ErrorLog /var/log/apache2/error.zarebski.io.com.log
Include /etc/letsencrypt/options-ssl-apache.conf
SSLCertificateFile /etc/letsencrypt/live/mydomain.io/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/mydomain.io/privkey.pem
</VirtualHost>

In case of multiple applications running on different ports and different local IP addresses the recommended method is using Reverse Proxy
Basically you configure your apache to forward requests to those services, i.e.:
<VirtualHost *:443>
ServerName sub.mydomain.io
ProxyPass "/wordpress" "http://172.17.0.2:8080/"
ProxyPass "/django" "http://172.17.0.2:8000/"
ErrorLog /var/log/apache2/error.mydomain.io.com.log
Include /etc/letsencrypt/options-ssl-apache.conf
SSLCertificateFile /etc/letsencrypt/live/mydomain.io/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/mydomain.io/privkey.pem
</VirtualHost>
If you have multpile external domain you can use Name Based Virtual hosts

Well, it took me a while to figure things out, for there was two main corner cases. I'll stick to one case: the wordpress image
<VirtualHost *:443>
ServerName new_domain.eu
ProxyPass / http://localhost:8081/
<Location />
AddOutputFilterByType SUBSTITUTE text/html
SetOutputFilter proxy-html
ProxyPassReverse /
Substitute "s|http://localhost:8081/|https://new_domain.eu/|i"
RequestHeader unset Accept-Encoding
</Location>
SSLCertificateFile /etc/letsencrypt/live/new_domain.eu/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/new_domain.eu/privkey.pem
Include /etc/letsencrypt/options-ssl-apache.conf
</VirtualHost>
[First of all], I could not access container from their local ip (i.e 172.7.0.3:80, not sure why), so I used the localhost port defined while setting the container up:
docker run -e WORDPRESS_DB_PASSWORD=thePassWord --name wordpress --link wordpressdb:mysql -p 8081:80 -v "$PWD/html":/var/www/html -d wordpress
[secondly] the tricky part was, then, to handle properly relative urls (e.g. some/path/to/css), for these were not accessible. Apparently, this is a well known issue. This part was the longest: things changed a lot around Apache 2.4 and the syntax is not well documented. Basically,
Substitute "s|http://localhost:8081/|https://new_domain.eu/|i"
replace all urls in html so that relative resources (css, js, png, etc etc) could be properly accessed.
[possible improvements] I am not quite happy with port 8081 being visible from the external world. It means that the app could be accessed from this very port, bypassing the rules I setted up in apache.conf. I fixed the issue by adding an iptables rule
iptables -A INPUT -p tcp -s localhost --dport 8081 -j ACCEPT
iptables -A INPUT -p tcp --dport 8081 -j DROP
Not quite elegant so if anyone has a suggestion, let me know.
\//_

Related

Moqui running in jetty container behind httpd returns Error rendering screen

I have an httpd server configured and working. The server returns "It works" and I can see the SSL is installed correctly.
The next step I undertook was configuring the reverse proxy, so that the users requests are redirected and I can have more customers' apps under one subdomain. The httpd configuration (shown below) I use is not mine, I am just attempting to reconfigure it to work for me. But with no big success up to now. There are directives that may be incorrect, but I have not tried commenting anything out.
#Apache is listening on port 443
Listen 443
SSLSessionCache shmcb:c:/Apache24/logs/shmcb_cache(512000)
SSLSessionCacheTimeout 300
Mutex default ssl-cache
SSLRandomSeed connect builtin
SSLCryptoDevice builtin
<VirtualHost *:443>
#ProxyPreserveHost On
SSLProxyEngine On
ServerName XXXX.sk
ServerAdmin admin
# Logs
ErrorLog /var/log/rsk_error_log
TransferLog /var/log/rsk_access_log
# Server Certificate and Private Key:
SSLCertificateFile /ssl/certificate.crt
SSLCertificateKeyFile /ssl/private.key
SSLCertificateChainFile /ssl/chain.crt
#Include conf/extra/proxy-443-to-8890.conf
ProxyPass /customer http://172.17.0.4:8080
ProxyPassReverse /customer http://172.17.0.4:8080
</VirtualHost>
Now when I type XXXX.sk/customer I receive a response which is a login screen, but it is incorrectly rendered, the CSS is not used at all. There are many errors appearing. When I log in, no response is returned and the URL is corrupted.
Can any of you, using httpd in a reverse proxy mode, please share your configs, at least a part of them?
The default webroot in base-component is mapping to / in url. All of resources like css, js etc is using "/" to build url, So Although the proxying is
ProxyPass /customer http://172.17.0.4:8080
The actual js location is still
/lib/jquery/jquery-ui.min.css
not
/customer/lib/jquery/jquery-ui.min.css
To make it work, the reverse proxy would need more messy location proxy_pass configurations.
So using additional path to proxy the webroot is not suggested.

Q: Disable access to default vhost and through server IP on Apache 2.4.10

I'm trying to get Apache 2.4.10 on Debian 8 "Jessie" up and running with multiple websites hosted on it. This might be an obvious and already answered question but I've never had the need to set-up a dedicated web host (usually just drop a WAMP server for development needs or pick up a web hosting service) and so far I have not had any luck finding an answer to my problem (I've found the complete opposite answers of what I'm trying to achieve). I need to get this working because apart from just hosting a couple of websites, there will be additional software set-up, for which, a regular web hosting service won't do.
Everything seems to be working as intended but the only problem is that I can't seem to find an optimal configuration which wouldn't just block access to default vhost with 403 - Forbidden. What I need is Apache to ignore requests (not just return a 404 document but tell the browser there's nothing there) from anyone accessing the default vhost or by accessing the server directly through it's designated IP. The designated IP should be left for SSH access only (since I don't have any kind of physical access to this server).
Basically, the web server should be accessible from a web browser through "FQDN-1" and "FQDN-2" (each located in their individual directories) and access to any other web address on this server should be ignored (invoking browser "404 not found" instead of returning a server error document, which would indicate that something is there).
my current vhost files:
<VirtualHost *:80>
ServerName FQDN-1
ServerAlias www.FQDN-1
ServerAdmin mail#FQDN-1
DocumentRoot /var/www/FQDN-1/public_html
ErrorLog /var/www/FQDN-1/logs/error.log
CustomLog /var/www/FQDN-1/logs/access.log combined
</VirtualHost>
And
<VirtualHost *:80>
ServerName FQDN-2
ServerAlias www.FQDN-2
ServerAdmin mail#FQDN-2
DocumentRoot /var/www/FQDN-2/public_html
ErrorLog /var/www/FQDN-2/logs/error.log
CustomLog /var/www/FQDN-2/logs/access.log combined
</VirtualHost>
The default vhost has been disabled through "a2dissite 000-default"
Iptables block everything except tcp port 80 and 22 (SSH access is whitelisted in iptables to just few specific iPs).
You can let the built-in name-based vhosting do the work for you. You can simply setup an additional (non default / non-first listed for *:80) virtualhost with
ServerName your-ip
and put a simple rule like
RewriteEngine ON
RewriteRule ^ .* [F]
or
Redirect 403 /

Apache reverse proxy, one server, multiple domains

I am trying to manage 2 domains with one server (running proxmox with several CT), I am using reverse proxy but seems to be wrong.. here's my configuration:
Let's say we have the main server running proxmox where I managed IPTables to redirect port 80 to the port 80 of my first container (CT01) and port 8109 to port 80 of my second container (CT02).
While using the port in my browser, everything is working well, and I am able to reach each container.
I bought 2 domain names, one for my private server (CT01) and another one for a business server (CT02). I associated both of the domain to my server address, and while typing one or another of them I am redirected to CT01 (normal, browser is running the address to the default port).
So now I tried to use reverse proxy in order to redirect to the desired server (DomainA -> CT01, DomainB -> CT02), I created 2 files in /var/apache2/sites-available/ :
/var/apache2/sites-available/domainA.com:
<VirtualHost *:80>
ServerName domainA.com
DocumentRoot /var/www/
</VirtualHost>
/var/apache2/sites-available/domainB.com:
<VirtualHost *:80>
ServerName domainB.com
ProxyPreserveHost On
ProxyRequests On
ProxyPass / http://x.y.z.h:8109/
ProxyPassReverse / http://x.y.z.h:8109/
<Location />
Order allow,deny
Allow from all
</Location>
</VirtualHost>
Then I runned a2ensite domainA.com and a2ensite domainB.com. I restarted my apache service.
But nothing have changed: both my domainA and domainB redirect me to the same container (CT01).
Any idea?
What i may suggest is doing a new CT just to host a proxy (nginx for example) that will route the requests to one or the other site depending of the Host: field value of the HTTP request. This may be a little bit overkill if it's just for two sites, but when you want to have more, it can be very useful. Plus the NGinx can be used to cache, etc.
Let me know if you are interested. I know a tutorial that you may follow, but it's in french : http://blog.ganbaranai.fr/2013/08/il-etait-une-fois-proxmox-derriere-une-ip-unique/
Hope it helps.
Regards,

Setup multiple SSL certificates on amazon VPC

I've been banging my head against the wall trying to figure out how to setup multiple SSL certificates on an amazon VPC instance (I'm using amazon's standard linux AMI)
Here's what I did:
I setup a VPC instance
Added a secondary private IP address
Added 2 elastic IP addresses & "linked" them to the private ones
Went to my domain registrar & pointed two test domains to the elastic IP addresses
Waited until new IP addresses were propagated
I uploaded the SSL certificates to the VPC instance
Then I tried editing ssl.conf, see line 74 to 93 & httpd.conf, see line 1046 to 1086:
ssl.conf
<VirtualHost domain1.com:443>
ServerName www.domain1.com:443
DocumentRoot "/var/www/html"
SSLENGINE on
SSLCertificateFile /etc/ssl/domain1_com.crt
SSLCertificateKeyFile /etc/ssl/domain1_com.key
SSLCertificateChainFile /etc/ssl/domain1_com.ca-bundle
</VirtualHost>
<VirtualHost _default_:443>
...Default SSL certificate (domain1.com) here...
</VirtualHost>
httpd.conf
<VirtualHost *:80>
ServerName domain1.com
ServerAlias www.domain1.com
DocumentRoot /var/www/html
ServerAdmin webmaster#domain1.com
</VirtualHost>
<VirtualHost *:80>
ServerName domain2.com
ServerAlias www.domain2.com
DocumentRoot /var/www/html
ServerAdmin webmaster#domain2.com
</VirtualHost>
I also tried <VirtualHost *:443> and <VirtualHost IP.ADDRESS:443>, didn't work either.
The result is basically this:
domain1.com (which is the default SSL certificate) works just fine (resolve fine, green bar)
domain2.com: doesn't even resolve to anything, even though when I do ping www.domain2.com, I get the correct elastic IP
My question is: Any idea how to make domain2.com resolve & use the correct SSL certificate?
EDIT / Additional Info:
I also tried this:
Temporarily stopped firewall as suggested, ie. sudo service iptables stop
From outside of EC2, curl --connect-timeout 10 https://domain2.com gave me this curl: (28) connect() timed out!
wget https://www.domain2.com/ gave me this: --2013-10-03 15:57:22-- domain2.com Resolving www.domain2.com... 54.229.111.22 Connecting to www.domain2.com|54.229.111.22|:443... failed: Connection timed out. Retrying.
EDIT (2):
I noticed 2 things:
If I use 2 network interfaces (each NIC with one private IP) sudo ifconfig doesn't show the 2nd NIC (ie. eth1), and wether I use one or two NICs, sudo ifconfig always return the 1st private IP (10.0.0.10), never the 2nd one (10.0.0.183)
Unsurprisingly, the unreachable website domain2.com corresponds to the 2nd IP (which is missing): 10.0.0.183
This command curl --interface 10.0.0.10 ifconfig.me correctly retuns the elastic IP address associated to domain1.com while
This command curl --interface 10.0.0.183 ifconfig.me retuns:
curl: (45) bind failed with errno 99: Cannot assign requested address
I followed this guid, I can see eth1, but domain2.com is still unreachable
And curl --interface 10.0.0.183 ifconfig.me now returns this:
curl: (7) Failed connect to ifconfig.me:80; Connection timed out
You will need to use ip based virtual hosting for SSL. The IP address you are going to listen will be the private, not public IP.
Your sites on port 80 can use name based virtual hosting. But you need to make sure you are using this directive: NameVirtualHost *:80
This tutorial fixed it for me
One small (but important) note:
Instead of typing this command (step #5):
echo "1 admin" >> /etc/iproute2/rt_tables
You should do this instead:
sudo vi /etc/iproute2/rt_tables
then add 1 admin at the end of the file
I think you need to follow a troubleshooting methodology for this.
Start by simplifying your configuration and verifying the basic components, then gradually build it up to the complete solution. For example:
Map the elastic IP for domain2 to a new EC2 server.
On the new server, start by making domain2.com available over HTTP
Once it is working over HTTP, set it up to work over HTTPS
Once it is working over HTTPS map the elastic IP back to the original server and make it work on the original server using HTTP
Once it is working over HTTP take the final step of getting it to work over HTTPS on the original server.
The aim here is to validate each step and isolate exactly where it is going wrong. This will then enable you to best direct your energies for solving the root cause.

Set up host file using port

I want to setup my host file to
127.0.0.2:5050 domain2.com => this is a local domain
when a type in my browser domain2.com, this return me : HTTP Error 404. The requested resource is not found.
i use this in apache
<VirtualHost 127.0.0.9:5050>
ServerAdmin info#domain2.com
DocumentRoot "C:/Users/My_Dir/LOOP/WebEnginer-2011/domain2_Dir/"
ServerName domain2.com
DirectoryIndex index.php index.html index.htm
ServerAlias www.domain2.com
ErrorLog "c:/wamp/xxxx/xxxx.log"
CustomLog "c:/wamp/xxxx/xxxx.log" common
</VirtualHost>
<VirtualHost 127.0.0.9:5050>
ServerAdmin info#domain2.com
DocumentRoot "C:/Users/My_Dir/LOOP/WebEnginer-2011/domain2_Dir/admin_Dir/"
ServerName admin.domain2.com
DirectoryIndex index.php index.html index.htm
ServerAlias www.admin.domain2.com
ErrorLog "c:/wamp/xxxx/xxxx.log"
CustomLog "c:/wamp/xxxx/xxxx.log" common
</VirtualHost>
but when i type 127.0.0.2:5050 i can see a web page. I want to use subdomain like admin.domain2.com
i can't use port 80 because IIS use that port.
How can i set up my host file to listen domain2.com?
That won't work since the hosts file only serves the purpose of mapping a hostname to an IP-address. The port number of a service is a different concept and is not handled by the "hosts" file nor the DNS-System. In Short: you can't supply a port number in the "hosts" file.
If your Webserver works on another port, you have to supply that information in the URL: http://domain2.com:5050.
The only other solution is to configure your Webservers to listen on a specific IP so that they don't interfere with each other. For example the IIS could listen on 127.0.0.1 and the Apache on 127.0.0.2 (the way you have already configured it).
There's a HOWTO for achieving that with the IIS. I'm not sure if that works for 127.0.0.x-IP's but I think it's worth a try.
It might be:
Your DNS resolver not resolving that properly
Some Apache webserver misconfiguration
Try this to get more information about that:
What if you ping domain2.com?
Also, try what happens if you put something like domain2.local in your hosts file. It might be some windows security c** disallowing you to overwrite the ip of an existing domain.
Why didn't you use 127.0.0.1? That should be fine, however
Make sure you have a properly configured VirtualHost that accepts requests to "domain2.com", or you just have a default virtualhost.
EDIT
What did you actually add to hosts file? The correct syntax would be:
127.0.0.2 domain2.com