Want to take your software engineering career to the next level? Join the mailing list for career tips & advice Click here


A fully automated HTTPS server powered by Nginx, Let's Encrypt and Docker.

Subscribe to updates I use https-portal

Statistics on https-portal

Number of watchers on Github 571
Number of open issues 3
Average time to close an issue 11 days
Main language Ruby
Average time to merge a PR 2 days
Open pull requests 5+
Closed pull requests 6+
Last commit over 2 years ago
Repo Created almost 5 years ago
Repo Last Updated over 2 years ago
Size 174 KB
Organization / Authorsteveltn
Latest Release1.2.4
Page Updated
Do you use https-portal? Leave a review!
View open issues (3)
View https-portal activity
View on github
Book a Mock Interview With Me (Silicon Valley Engineering Leader, 100s of interviews conducted)
Software engineers: It's time to get promoted. Starting NOW! Subscribe to my mailing list and I will equip you with tools, tips and actionable advice to grow in your career.
Evaluating https-portal for your project? Score Explanation
Commits Score (?)
Issues & PR Score (?)


HTTPS-PORTAL is a fully automated HTTPS server powered by Nginx, Let's Encrypt and Docker. By using it, you can run any existing web application over HTTPS, with only one extra line of configuration.

The SSL certificates are obtained, and renewed from Let's Encrypt automatically.

Docker Hub page: https://hub.docker.com/r/steveltn/https-portal/

Table of Contents


HTTPS-PORTAL is shipped as a Docker image. To use it, you need a Linux machine (either local or remote host) which:

  • Has 80 and 443 port available and exposed.
  • Has Docker Engine installed. In addition, Docker Compose is highly recommended, for it makes your life easier. Examples in our documents are mainly in Docker Compose format.
  • Has all domains you're going to use in the following examples resolving to it.

Though it is good to have, knowledge about Docker is not required to use HTTPS-PORTAL.

See It Work

Create a docker-compose.yml file with the following content in any directory of your choice:

  image: steveltn/https-portal:1
    - '80:80'
    - '443:443'
    DOMAINS: 'example.com'
    # STAGE: 'production'

Run the docker-compose up command in the same directory. A moment later you'll have a welcome page running in https://example.com.

Quick Start

Here is a more real-world example: Create the file docker-compose.yml in another directory:

  image: steveltn/https-portal:1
    - '80:80'
    - '443:443'
    - wordpress
  restart: always
    DOMAINS: 'wordpress.example.com -> http://wordpress'
    # STAGE: 'production'
    # FORCE_RENEW: 'true'

  image: wordpress
    - db:mysql

  image: mariadb
    MYSQL_ROOT_PASSWORD: '<a secure password>'

Run the docker-compose up -d command. A moment later you'll get a WordPress running on https://wordpress.example.com.

In the example above, only the environment variables under the https-portal section are HTTPS-PORTAL specific configurations. This time we added an extra parameter -d, which will tell Docker Compose to run the apps defined in docker-compose.yml in the background.

Note: STAGE is staging by default, which results in a test (untrusted) certificate from Let's Encrypt.


Test Locally

You can test HTTPS-PORTAL with your application stack locally.

  # ...
    STAGE: local
    DOMAINS: 'example.com'

By doing this, HTTPS-PORTAL will create a self-signed certificate. This certificate is not likely to be trusted by your browser, but you can use it to test your docker-compose file. Make sure it works with your application stack.

Note that HTTPS-PORTAL only listens to example.com, as you specified in the compose file. In order to make HTTPS-PORTAL respond to your connection, you need to either:

  • modify your hosts file to have example.com resolving to your docker host,


  • set up DNSMasq on your computer/router. This method provides more flexibility.

Once you are done testing, you can deploy your application stack to the server.


HTTPS-PORTAL support quick setup for redirections. It is deliberately made to support https targets only because otherwise it'd be against the idea of this project.

  # ...
    STAGE: local
    DOMAINS: 'example.com => target.example.com/foo/bar' # Notice it's "=>" instead of the normal "->"

Automatic Container Discovery

HTTPS-PORTAL is capable of discovering other Docker containers running on the same host, as long as the Docker API socket is accessible within the container.

In order to make it so, launch HTTPS-PORTAL using the following docker-compose.yml.

version: '2'

    # ...
      - /var/run/docker.sock:/var/run/docker.sock:ro

and launch one or more web applications with:

version: '2'

    # ...
      - '8080:80'
      # tell HTTPS-PORTAL to set up "example.com"
      VIRTUAL_HOST: example.com

Caveat: Your web application must be created in the same network as HTTPS-PORTAL.

Note that here is no need to link your web service to HTTPS-PORTAL, and you shouldn't put example.com in environment variable DOMAINS of HTTP-PORTAL.

This feature allows you to deploy multiple web applications on the same host without restarting HTTPS-PORTAL itself or interrupting any other application while adding/removing web applications.

If your web service has more than one port exposed (mind that ports can be exposed in your web service Dockerfile), use the environment variable VIRTUAL_PORT to specify which port accepts HTTP requests:

  # ...
    - '8080:80'
    - '2222:22'
    VIRTUAL_HOST: example.com
    VIRTUAL_PORT: '8080'

Of course container discovery works in combination with ENV specified domains:

  # ...
    - /var/run/docker.sock:/var/run/docker.sock:ro
    DOMAINS: 'example.com -> http://upstream'

Hybrid Setup with Non-Dockerized Apps

Web applications that run directly on the host machine instead of in Docker containers are available at dockerhost.

For instance, if an application accepts HTTP requests on port 8080 of the host machine, you can start HTTPS-PORTAL by:

  # ...
    DOMAINS: 'example.com -> http://dockerhost:8080'

Multiple Domains

You can specify multiple domains by splitting them with commas:

  # ...
    DOMAINS: 'wordpress.example.com -> http://wordpress, gitlab.example.com
    -> http://gitlab'

You can also specify the stage (local, staging, or production) for each individual site, note that stages of individual sites overrides the global stage:

DOMAINS: 'wordpress.example.com -> http://wordpress #local, gitlab.example.com #production'

Serving Static Sites

Instead of forwarding requests to web applications, HTTPS-PORTAL can also serve (multiple) static sites directly:

  # ...
    DOMAINS: 'hexo.example.com, octopress.example.com'
    - /data/https-portal/vhosts:/var/www/vhosts

After HTTPS-PORTAL is started, it will create corresponding sub-directories for each virtual host in the /data/https-portal/vhosts directory on the host machine:


You can place your own static files in this directory hierarchy, they will not be overwritten. You need an index.html to be served as the homepage.

Share Certificates with Other Apps

You can mount an arbitrary host directory to /var/lib/https-portal as a data volume.

For instance:

  # ...
    - /data/ssl_certs:/var/lib/https-portal

Now your certificates are available in /data/ssl_certs on your host.

Advanced Usage

Configure Nginx through Environment Variables

There are several additional environment variables that you can use to config Nginx. They correspond to the configuration options that you would normally supply in nginx.conf. The following are the config keys with default values:

SERVER_NAMES_HASH_BUCKET_SIZE=32        # defaults to 32 or 64 based on your CPU
CLIENT_MAX_BODY_SIZE=1M                 # 0 disables checking request body size
PROXY_BUFFERS="8 4k"                    # Either 4k or 8k depending on the platform
PROXY_BUFFER_SIZE="4k"                  # Either 4k or 8k depending on the platform
RESOLVER="Your custom solver string"

You can also add


to make HTTPS-PORTAL proxy WEBSOCKET connections.

To avoid nginx DNS caching activate dynamic upstream

RESOLVER=" ipv6=off valid=30s"

Override Nginx Configuration Files

You can override default nginx settings by providing a config segment of nginx.conf containing a valid server block. The custom nginx configurations are ERB templates and will be rendered before usage.

For instance, to override both HTTPS and HTTP settings for my.example.com, you can launch HTTPS-PORTAL by:

  # ...
    - /path/to/http_config:/var/lib/nginx-conf/my.example.com.conf.erb:ro
    - /path/to/https_config:/var/lib/nginx-conf/my.example.com.ssl.conf.erb:ro

This file and this file are the default configuration files used by HTTPS-PORTAL. You can probably start by copying these files and make modifications to them.

Another example can be found here.

If you want to make an Nginx configuration that will be used by all sites, you can overwrite /var/lib/nginx-conf/default.conf.erb or /var/lib/nginx-conf/default.ssl.conf.erb. These two files will be propagated to each site if the site-specific configuration files are not provided.

How It Works


  • obtains an SSL certificate for each of your subdomains from Let's Encrypt.
  • configures Nginx to use HTTPS (and force HTTPS by redirecting HTTP to HTTPS)
  • sets up a cron job that checks your certificates every week, and renew them. if they expire in 30 days.

About Rate Limits of Let's Encrypt

Let's Encrypt is in public beta at the moment. According to this and this discussion, the rate limits are

  • 10 registrations per IP per 3 hours.
  • 5 certificates per domain (not sub-domain) per 7 days.

The former is not usually a problem, however the latter could be, if you want to apply certificates for multiple sub-domains on a single domain. Let's Encrypt does support SAN certificates, however it requires careful planning and is hard to automate. So in HTTPS-PORTAL we only deal with CN certificates.

HTTPS-PORTAL stores your certificates in a data volume and will not re-sign certificates until 30 days before expiration if a valid certificate is found (you can force renew certificates by using FORCE_RENEW: 'true' environment variable). However if you play around with the image a lot, you can hit the limit. That's why STAGE is staging by default, and thus we use the Let's Encrypt staging server. When you have finished your experiments and feel everything is good, you can switch to production mode with STAGE: 'production'.

According to Let's Encrypt, the restrictions will be loosened over time.


https-portal open issues Ask a question     (View All Issues)
  • almost 4 years Default redirections are made to http
  • about 4 years Vhost not working after failed cert renew attempt
  • about 4 years Advised to mount certs folder?
https-portal open pull requests (View All Pulls)
  • Allow WebSocket proxying
  • Adds environment variables for proxy buffers
  • Allows ENVs to set proxy timeout parameters
  • Handle null domains
  • Update README.md
https-portal questions on Stackoverflow (View All Questions)
  • Why the "See It Work" section of the Docker https-portal gives me a "port 443: Connection refused" error?
https-portal list of languages used
https-portal latest release notes
1.2.4 v1.2.4

Fix the issue where cron jobs don't get environment variables.

1.2.3 v1.2.3
  • Update the message in the welcome screen
1.2.2 v1.2.2
  • Bugfix: dockerhost upstream didn't work.
Other projects in Ruby
Powered by Autocode - Instant Webhooks, Scripts and APIs
Autocode logo wordmark