I searched already that it has something to the redirect module in apache, but I decided to ask here if someone can give me a direction where I should follow, because I am a bit lost.

The current situation is: I have a droplet with CentOS 7 x64 and within this droplet my docker user with some docker containers (just showing 2 to better exemplify):

CONTAINER ID        IMAGE                     COMMAND                  CREATED             STATUS              PORTS                      NAMES
f381c6a9a341        image1                  "docker-entrypoint..."   4 weeks ago         Up 3 weeks          0.0.0.0:15435->5432/tcp    app1_postgres
69fb1e99b463        image2-nodejs_web      "/docker-entrypoin..."   3 weeks ago          Up 3 weeks          0.0.0.0:10443->443/tcp   app1_nodejs

There is a container for the nodejs app and another container of the database for this app. Everything works and they can communicate with each other.

Besides, in this same droplet (outside docker) I have the user apache where I run httpd with my static portfolio in my custom domain https://www.myportfolio.dev.

What I would like: If I access https://www.myportfolio.dev/apps/app1 it redirects somehow from the apache to the docker container running my nodejs app in the exposed port 10443.

What I could do until now: if someone access https://www.myportfolio.dev:10443, which is the https port I have opened for the nodejs container, the app is accessible, but this is not the approach I want. I want to have the /apps/APP_NAME in the url redirecting to the specific containers.

Additional info 1: I usually have routes in my nodejs and react apps, for example:

https://myapp.com/
https://myapp.com/login
https://myapp.com/home
https://myapp.com/products
https://myapp.com/insert

among other routes, and the redirect should work fine for this routes also.

Additional info 2: Either in my portfolio either in my apps I always use SSL. Please correct me if I am wrong, but the SSL key pairs for my portfolio can also be used for all my apps, because the apache httpd remains the same, it will be used as a “proxy” !?

Additional Question: Should I also create a subdomain for this app from the example before I configure them in apache? Something like CNAME e.g. myapp1.myportfolio.dev?

I would be really thankful for every help I receive here.

Thanks in advance!

Best Regards,
Gabriel

These answers are provided by our Community. If you find them useful, show some love by clicking the heart. If you run into issues leave a comment, or add your own answer to help others.

×
3 answers

Hi there @gabrielbrde,

What you could do is configure Apache as a reverse proxy, that way you can have the traffic for specify different URLs to be proxied to specific Docker containers, for example, it would look something like this:

    ProxyPreserveHost On

    ProxyPass /apps/APP_NAME http://127.0.0.1:15435/
    ProxyPassReverse /apps/APP_NAME http://127.0.0.1:15435/

You can take a look at this tutorial here on how to configure Apache as a Reverse Proxy with mod_proxy:

https://www.digitalocean.com/community/tutorials/how-to-use-apache-as-a-reverse-proxy-with-mod_proxy-on-ubuntu-16-04

Hope that this helps!
Regards,
Bobby

by Mateusz Papiernik
In this tutorial, you will set up Apache as a reverse proxy using the `mod_proxy` extension to redirect incoming connections to underlying application server(s) running on the same network. There are instructions on setting up a simple web app using the Flask framework to show how Apache interacts with the real application hidden behind it, but you can also follow this tutorial using your existing application server, if you have one.
  • Hey Bobby,

    many thanks for the answer.

    I followed the steps in the link you wrote, but it seems there are no results after changing and restarting apache httpd.

    Even adding this:

        ProxyPreserveHost On
    
        ProxyPass /apps/app1 https://127.0.0.1:10443/
        ProxyPassReverse /apps/app1 https://127.0.0.1:10443/
    

    In a configuration file and calling it at the end of httpd.conf, I can still access https://mywebsite.dev:10443 and it works, but with the route /apps/app1 it doesn’t.

    Is there a specific order it should be added? Maybe I can share my configuration here:

    The ending lines of httpd.conf (I removed IncludeOptional and set Include to check if there was a file not being called).

    [...]
    # Supplemental configuration
    #
    # Load config files in the "/etc/httpd/conf.d" directory, if any.
    Include conf.d/*.conf
    Include sites-enabled/*.conf
    Include /etc/httpd/sites-available/mywebsite.dev-le-ssl.conf
    
    

    /etc/httpd/conf.d/ssl.conf (I removed most of comments to simplify it):

    Listen 443 https
    
    SSLPassPhraseDialog exec:/usr/libexec/httpd-ssl-pass-dialog
    
    SSLSessionCache         shmcb:/run/httpd/sslcache(512000)
    SSLSessionCacheTimeout  300
    
    SSLRandomSeed startup file:/dev/urandom  256
    SSLRandomSeed connect builtin
    #SSLRandomSeed startup file:/dev/random  512
    #SSLRandomSeed connect file:/dev/random  512
    #SSLRandomSeed connect file:/dev/urandom 512
    
    SSLCryptoDevice builtin
    #SSLCryptoDevice ubsec
    
    
    ## SSL Virtual Host Context
    
    <VirtualHost _default_:443>
    
    # General setup for the virtual host, inherited from global configuration
    #DocumentRoot "/var/www/html"
    #ServerName www.example.com:443
    
    
    ErrorLog logs/ssl_error_log
    TransferLog logs/ssl_access_log
    LogLevel warn
    
    SSLEngine on
    
    SSLProtocol all -SSLv2 -SSLv3
    
    SSLCipherSuite HIGH:3DES:!aNULL:!MD5:!SEED:!IDEA
    
    
    #SSLCipherSuite RC4-SHA:AES128-SHA:HIGH:MEDIUM:!aNULL:!MD5
    #SSLHonorCipherOrder on 
    
    
    SSLCertificateFile /etc/pki/tls/certs/localhost.crt
    
    
    SSLCertificateKeyFile /etc/pki/tls/private/localhost.key
    
    
    #SSLCertificateChainFile /etc/pki/tls/certs/server-chain.crt
    
    
    #SSLCACertificateFile /etc/pki/tls/certs/ca-bundle.crt
    
    
    #SSLVerifyClient require
    #SSLVerifyDepth  10
    
    
    #<Location />
    #SSLRequire (    %{SSL_CIPHER} !~ m/^(EXP|NULL)/ \
    #            and %{SSL_CLIENT_S_DN_O} eq "Snake Oil, Ltd." \
    #            and %{SSL_CLIENT_S_DN_OU} in {"Staff", "CA", "Dev"} \
    #            and %{TIME_WDAY} >= 1 and %{TIME_WDAY} <= 5 \
    #            and %{TIME_HOUR} >= 8 and %{TIME_HOUR} <= 20       ) \
    #           or %{REMOTE_ADDR} =~ m/^192\.76\.162\.[0-9]+$/
    #</Location>
    
    <Files ~ "\.(cgi|shtml|phtml|php3?)$">
        SSLOptions +StdEnvVars
    </Files>
    <Directory "/var/www/cgi-bin">
        SSLOptions +StdEnvVars
    </Directory>
    
    BrowserMatch "MSIE [2-5]" \
             nokeepalive ssl-unclean-shutdown \
             downgrade-1.0 force-response-1.0
    
    CustomLog logs/ssl_request_log \
              "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"
    
    </VirtualHost>                  
    

    /etc/httpd/sites-available/mywebsite.dev.conf:

    <VirtualHost *:80>
        ServerName www.mywebsite.dev
        ServerAlias mywebsite.dev
        DocumentRoot /var/www/mywebsite.dev/html
        ErrorLog /var/www/mywebsite.dev/log/error.log
        CustomLog /var/www/mywebsite.dev/log/requests.log combined  
    RewriteEngine on
    RewriteCond %{SERVER_NAME} =mywebsite.dev [OR]
    RewriteCond %{SERVER_NAME} =www.mywebsite.dev
    RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
    </VirtualHost>
    

    /etc/httpd/sites-available/mywebsite.dev-le-ssl.conf:

    <IfModule mod_ssl.c>
    <VirtualHost *:443>
        ServerName www.mywebsite.dev
        ServerAlias mywebsite.dev
        DocumentRoot /var/www/mywebsite.dev/html
        ErrorLog /var/www/mywebsite.dev/log/error.log
        CustomLog /var/www/mywebsite.dev/log/requests.log combined
    Include /etc/letsencrypt/options-ssl-apache.conf
    SSLCertificateFile /etc/letsencrypt/live/mywebsite.dev/cert.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/mywebsite.dev/privkey.pem
    SSLCertificateChainFile /etc/letsencrypt/live/mywebsite.dev/chain.pem
    </VirtualHost>
    </IfModule>
    
    

    /etc/httpd/sites-available/myapp.conf:

    <VirtualHost *:443>
        ProxyPreserveHost On
    
        ProxyPass /apps/app1 https://127.0.0.1:10443/
        ProxyPassReverse /apps/app1 https://127.0.0.1:10443/
    </VirtualHost>
    
    

    Sorry for keep asking but I do not understand what could be wrong here.

    • Hi there @gabrielbrde,

      The configuration looks correct, but I think that mod_proxy might be missing.

      In order to add it to your CentOS 7 server, you could follow the steps here:

      https://www.digitalocean.com/community/tutorials/how-to-use-apache-as-a-reverse-proxy-with-mod_proxy-on-centos-7

      Then once this has been enabled in order to check if the module is active, you could run:

      • httpd -M

      Let me know how it goes!
      Regards,
      Bobby

      by Mateusz Papiernik
      In this tutorial, you will set up Apache as a reverse proxy using the `mod_proxy` extension to redirect incoming connections to underlying application server(s) running on the same network. There are instructions on setting up a simple web app using the Flask framework to show how Apache interacts with the real application hidden behind it, but you can also follow this tutorial using your existing application server, if you have one.
      • The modules were already enabled:

        [apache@centos-01 sites-available]$ sudo cat /etc/httpd/conf.modules.d/00-proxy.conf
        # This file configures all the proxy modules:
        LoadModule proxy_module modules/mod_proxy.so
        LoadModule lbmethod_bybusyness_module modules/mod_lbmethod_bybusyness.so
        LoadModule lbmethod_byrequests_module modules/mod_lbmethod_byrequests.so
        LoadModule lbmethod_bytraffic_module modules/mod_lbmethod_bytraffic.so
        LoadModule lbmethod_heartbeat_module modules/mod_lbmethod_heartbeat.so
        LoadModule proxy_ajp_module modules/mod_proxy_ajp.so
        LoadModule proxy_balancer_module modules/mod_proxy_balancer.so
        LoadModule proxy_connect_module modules/mod_proxy_connect.so
        LoadModule proxy_express_module modules/mod_proxy_express.so
        LoadModule proxy_fcgi_module modules/mod_proxy_fcgi.so
        LoadModule proxy_fdpass_module modules/mod_proxy_fdpass.so
        LoadModule proxy_ftp_module modules/mod_proxy_ftp.so
        LoadModule proxy_http_module modules/mod_proxy_http.so
        LoadModule proxy_scgi_module modules/mod_proxy_scgi.so
        LoadModule proxy_wstunnel_module modules/mod_proxy_wstunnel.so
        
        [apache@centos-01 sites-available]$ sudo httpd -M
        Loaded Modules:
         core_module (static)
         so_module (static)
         http_module (static)
         access_compat_module (shared)
         actions_module (shared)
         alias_module (shared)
         allowmethods_module (shared)
         auth_basic_module (shared)
         auth_digest_module (shared)
         authn_anon_module (shared)
         authn_core_module (shared)
         authn_dbd_module (shared)
         authn_dbm_module (shared)
         authn_file_module (shared)
         authn_socache_module (shared)
         authz_core_module (shared)
         authz_dbd_module (shared)
         authz_dbm_module (shared)
         authz_groupfile_module (shared)
         authz_host_module (shared)
         authz_owner_module (shared)
         authz_user_module (shared)
         autoindex_module (shared)
         cache_module (shared)
         cache_disk_module (shared)
         data_module (shared)
         dbd_module (shared)
         deflate_module (shared)
         dir_module (shared)
         dumpio_module (shared)
         echo_module (shared)
         env_module (shared)
         expires_module (shared)
         ext_filter_module (shared)
         filter_module (shared)
         headers_module (shared)
         include_module (shared)
         info_module (shared)
         log_config_module (shared)
         logio_module (shared)
         mime_magic_module (shared)
         mime_module (shared)
         negotiation_module (shared)
         remoteip_module (shared)
         reqtimeout_module (shared)
         rewrite_module (shared)
         setenvif_module (shared)
         slotmem_plain_module (shared)
         slotmem_shm_module (shared)
         socache_dbm_module (shared)
         socache_memcache_module (shared)
         socache_shmcb_module (shared)
         status_module (shared)
         substitute_module (shared)
         suexec_module (shared)
         unique_id_module (shared)
         unixd_module (shared)
         userdir_module (shared)
         version_module (shared)
         vhost_alias_module (shared)
         dav_module (shared)
         dav_fs_module (shared)
         dav_lock_module (shared)
         lua_module (shared)
         mpm_prefork_module (shared)
         proxy_module (shared)
         lbmethod_bybusyness_module (shared)
         lbmethod_byrequests_module (shared)
         lbmethod_bytraffic_module (shared)
         lbmethod_heartbeat_module (shared)
         proxy_ajp_module (shared)
         proxy_balancer_module (shared)
         proxy_connect_module (shared)
         proxy_express_module (shared)
         proxy_fcgi_module (shared)
         proxy_fdpass_module (shared)
         proxy_ftp_module (shared)
         proxy_http_module (shared)
         proxy_scgi_module (shared)
         proxy_wstunnel_module (shared)
         ssl_module (shared)
         systemd_module (shared)
         cgi_module (shared)
        
        

Hello everyone, just a short update:

Yesterday I saw my error, I could access https://mywebsite.dev:10443 because I was running docker with 0.0.0.0 (which means the docker container was also reachable for outside).

I corrected it by changing to 127.0.0.1 in the docker-compose.yml:

version: "3.7"
services:
  db:
    image: postgres:alpine
    command: -p 5435
    environment:
      POSTGRES_USER: psgadmin
      POSTGRES_PASSWORD: 12345
      PG_PORT: 5435
      POSTGRES_DB: snippetfy
    volumes:
      - pgdata:/var/lib/postgresql/data
    restart: always
    networks:
      - app-network
    container_name: postgres-db

  web:
    build: .
    depends_on:
      - db
    ports:
      - 127.0.0.1:10443:10443      
    volumes:
      - webapp:/home/node/app
      - /home/node/app/node_modules
    environment:
      DATABASE_URL: ${DATABASE_URL}
      NODE_ENV: ${NODE_ENV}
    networks:
      - app-network
    container_name: snippetfy-node
    hostname: snippetfy-node

volumes:
  pgdata:
  webapp:

networks:
  app-network:
    driver: bridge

Now at least I cannot reach anymore by typing https://mywebsite.dev:10443.

However my problem is still not solved, I do not know what else I can do to make the proxy works correctly and finally access my app(s) through https://mywebsite.dev/apps/app_name.

I am thankful for every help!

Best Regards,
Gabriel

  • Hi there @gabrielbrde,

    I can see that you have the Proxy virtual host in your sites-available folder, have you enabled the virtual host and if so is it present in the sites-enabled folder?

    If this still does not work, I would recommend checking your Apache error and access logs for some more information, feel free to share the output of the logs here.

    Also what happens currently if you visit the /apps/APP_NAME URL?

    Regards,
    Bobby

    • Hello @bobbyiliev,

      this is the content of sites-available/enabled:

      sites-available
      ├── myapp1.conf
      ├── mywebsite.dev.conf
      └── mywebsite.dev-le-ssl.conf
      sites-enabled
      ├── myapp1.conf -> /etc/httpd/sites-available/myapp1.conf
      └── mywebsite.dev.conf -> /etc/httpd/sites-available/mywebsite.dev.conf
      

      Found some interesting stuff here in the error-log-20200503:

      [Sat May 02 19:01:45.575879 2020] [core:notice] [pid 31756] SELinux policy enabled; httpd running as context system_u:system_r:httpd_t:s0
      [Sat May 02 19:01:45.577105 2020] [suexec:notice] [pid 31756] AH01232: suEXEC mechanism enabled (wrapper: /usr/sbin/suexec)
      [Sat May 02 19:01:45.578409 2020] [ssl:warn] [pid 31756] AH02292: Init: Name-based SSL virtual hosts only work for clients with TLS server name indication support (RFC 4366)
      [Sat May 02 19:01:45.603563 2020] [lbmethod_heartbeat:notice] [pid 31756] AH02282: No slotmem from mod_heartmonitor
      [Sat May 02 19:01:45.604937 2020] [ssl:warn] [pid 31756] AH02292: Init: Name-based SSL virtual hosts only work for clients with TLS server name indication support (RFC 4366)
      [Sat May 02 19:01:45.614078 2020] [mpm_prefork:notice] [pid 31756] AH00163: Apache/2.4.6 (CentOS) OpenSSL/1.0.2k-fips configured -- resuming normal operations
      [Sat May 02 19:01:45.614117 2020] [core:notice] [pid 31756] AH00094: Command line: '/usr/sbin/httpd -D FOREGROUND'
      
      

      ssl-access-log:

      83.97.20.29 - - [03/May/2020:03:57:05 +0000] "GET / HTTP/1.1" 400 226
      162.243.143.239 - - [03/May/2020:04:29:42 +0000] "GET / HTTP/1.1" 403 4897
      128.14.133.58 - - [03/May/2020:05:51:35 +0000] "GET /cgi-bin/config.exp HTTP/1.1" 404 216
      178.128.194.144 - - [03/May/2020:06:57:47 +0000] "GET / HTTP/1.0" 400 362
      178.128.194.144 - - [03/May/2020:06:57:47 +0000] "GET / HTTP/1.1" 403 4897
      174.95.160.125 - - [03/May/2020:09:21:22 +0000] "GET / HTTP/1.0" 400 362
      174.95.160.125 - - [03/May/2020:09:21:23 +0000] "GET / HTTP/1.0" 400 362
      46.5.5.17 - - [03/May/2020:13:26:51 +0000] "-" 408 -
      
      

      ssl-error-log:

      [Sun May 03 04:29:42.725371 2020] [autoindex:error] [pid 29772] [client 162.243.143.239:47644] AH01276: Cannot serve directory /var/www/html/: No matching DirectoryIndex (index.html) found, and server-generated directory index forbidden by Options directive
      [Sun May 03 05:51:35.533369 2020] [cgi:error] [pid 31425] [client 128.14.133.58:44362] script not found or unable to stat: /var/www/cgi-bin/config.exp
      [Sun May 03 06:57:47.517982 2020] [autoindex:error] [pid 29774] [client 178.128.194.144:46330] AH01276: Cannot serve directory /var/www/html/: No matching DirectoryIndex (index.html) found, and server-generated directory index forbidden by Options directive
      

      Also I am not sure if that helps somehow, but I have followed those 2 tutorials to make everything:

      https://www.digitalocean.com/community/tutorials/how-to-install-the-apache-web-server-on-centos-7

      https://www.digitalocean.com/community/tutorials/how-to-secure-apache-with-let-s-encrypt-on-centos-7

      by Vadym Kalsin
      by Erika Heidi
      SSL certificates are used within web servers to encrypt the traffic between the server and client, providing extra security for users accessing your application. Let’s Encrypt provides an easy way to obtain and install trusted certificates for free. This tutorial will show you how to set up a TLS/SSL certificate from Let’s Encrypt on a CentOS 7 server running Apache as a web server. Additionally, we will cover how to automate the certificate renewal process using a cron job.
      • Hi there @gabrielbrde,

        What happens if you try to access your server IP address followed by /apps/app1, so something like this: http://your_server_ip/apps/app1.

        Do you get to your Docker container on port 10443 or does it timeout?

        I think that you just need to move your proxy rules from your myapp.conf config to your virtual host for your domain name.

        I just deployed a Droplet and created a similar setup with a Docker service and Apache reverse proxy, and I can confirm that adding the proxy rules to the bottom of the virtual host for my domain works as expected.

        Let me know how it goes!
        Regards,
        Bobby

        • Hello @bobbyiliev ,

          if I access https://mywebsite.dev/apps/app1 it gives me: 404 Not found. The requested URL /apps/app1 was not found on this server.

          I can reach the docker container from outside if instead of this:

          CONTAINER ID        IMAGE                     COMMAND                  CREATED             STATUS              PORTS                        NAMES
          3a9b52a4491f        myapp-nodejs_web      "/docker-entrypoin..."   2 days ago          Up 2 days           127.0.0.1:10443->10443/tcp   myapp-node
          

          I do like this:

          CONTAINER ID        IMAGE                     COMMAND                  CREATED             STATUS              PORTS                        NAMES
          3a9b52a4491f        myapp-nodejs_web      "/docker-entrypoin..."   2 days ago          Up 2 days           0.0.0.0:10443->10443/tcp   myapp-node
          

          But then I come across that problem, that I access it only through https://mywebsite.dev:10443 instead of https://mywebsite.dev/apps/app1.

          Regarding configuration I followed your suggestion and changed some things, so now it is:

          httpd.conf:

          # Supplemental configuration
          #
          # Load config files in the "/etc/httpd/conf.d" directory, if any.
          Include conf.d/*.conf
          Include sites-enabled/*.conf
          
          

          and under sites-enabled:

          lrwxrwxrwx. 1 root root 46 Apr  5 20:28 mywebsite.dev.conf -> /etc/httpd/sites-available/mywebsite.dev.conf
          lrwxrwxrwx. 1 root root 53 May  5 18:16 mywebsite.dev-le-ssl.conf -> /etc/httpd/sites-available/mywebsite.dev-le-ssl.conf
          
          

          and then under sites-available/mywebsite.dev.conf:

          <VirtualHost *:80>
              ServerName www.mywebsite.dev
              ServerAlias mywebsite.dev
              DocumentRoot /var/www/mywebsite.dev/html
              ErrorLog /var/www/mywebsite.dev/log/error.log
              CustomLog /var/www/mywebsite.dev/log/requests.log combined  
          RewriteEngine on
          RewriteCond %{SERVER_NAME} =mywebsite.dev [OR]
          RewriteCond %{SERVER_NAME} =www.mywebsite.dev
          RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
          </VirtualHost>
          
          <VirtualHost *:443>
              ProxyPreserveHost On
          
              ProxyPass /apps/app1 https://127.0.0.1:10443
              ProxyPassReverse /apps/app1 https://127.0.0.1:10443
          </VirtualHost>
          
          

          and finally under sites-available/mywebsite.dev-le-ssl.conf:

          <IfModule mod_ssl.c>
          <VirtualHost *:443>
              ServerName www.mywebsite.dev
              ServerAlias mywebsite.dev
              DocumentRoot /var/www/mywebsite.dev/html
              ErrorLog /var/www/mywebsite.dev/log/error.log
              CustomLog /var/www/mywebsite.dev/log/requests.log combined
          Include /etc/letsencrypt/options-ssl-apache.conf
          SSLCertificateFile /etc/letsencrypt/live/mywebsite.dev/cert.pem
          SSLCertificateKeyFile /etc/letsencrypt/live/mywebsite.dev/privkey.pem
          SSLCertificateChainFile /etc/letsencrypt/live/mywebsite.dev/chain.pem
          </VirtualHost>
          </IfModule>
          
          

          After doing those changes and restarting, unfortunatelly it shows 404 Not found. I have no idea where the error could be. Searching in the internet it seems simple this redirecting, but with Docker it got complicated somehow.

          Thanks in advance and best regards,

          Gabriel

          • very later but…

            when i used apache reverse proxy i needed do that path exists before last slash.

            Example
            to use apache reverse proxy with url www.example.com/tools/report

            should be exists www.example.com/tools

            In your case

            <VirtualHost *:443>
                ProxyPreserveHost On
            
                ProxyPass /apps/app1 https://127.0.0.1:10443
                ProxyPassReverse /apps/app1 https://127.0.0.1:10443
            </VirtualHost>
            

            to can use https://mywebsite.dev/apps/app1 need that exists https://mywebsite.dev/apps

            can create a empty directory or use mod rewrite of apache

            can try use next proxy setting to know if work

            <VirtualHost *:443>
                ProxyPreserveHost On
            
                ProxyPass /app1 https://127.0.0.1:10443
                ProxyPassReverse /app1 https://127.0.0.1:10443
            </VirtualHost>
            

Hi @tinieblas ,

thanks for your reply to my post.

I tried what you said but I still get errors and do not really know how to fix it.

Maybe a better idea would be to create subdomains and use them instead of using my portfolio domain to it.

Kind Regards

Submit an Answer