[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-7753":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":10,"totalLinesOfCode":10,"stars":12,"forks":13,"watchers":14,"openIssues":15,"contributorsCount":16,"subscribersCount":16,"size":16,"stars1d":16,"stars7d":17,"stars30d":18,"stars90d":16,"forks30d":16,"starsTrendScore":16,"compositeScore":19,"rankGlobal":10,"rankLanguage":10,"license":20,"archived":21,"fork":21,"defaultBranch":22,"hasWiki":23,"hasPages":21,"topics":24,"createdAt":10,"pushedAt":10,"updatedAt":25,"readmeContent":26,"aiSummary":27,"trendingCount":16,"starSnapshotCount":16,"syncStatus":28,"lastSyncTime":29,"discoverSource":30},7753,"https-portal","SteveLTN\u002Fhttps-portal","SteveLTN","A fully automated HTTPS server powered by Nginx, Let's Encrypt and Docker.","",null,"Ruby",4694,295,83,50,0,3,9,29.41,"MIT License",false,"master",true,[],"2026-06-12 02:01:44","# HTTPS-PORTAL\n\nHTTPS-PORTAL is a fully automated HTTPS server powered by\n[Nginx](http:\u002F\u002Fnginx.org), [Let's Encrypt](https:\u002F\u002Fletsencrypt.org) and\n[Docker](https:\u002F\u002Fwww.docker.com). By using it, you can run any existing web\napplication over HTTPS, with only one extra line of configuration.\n\nThe SSL certificates are obtained, and renewed from Let's Encrypt\nautomatically.\n\nDocker Hub page:\n[https:\u002F\u002Fhub.docker.com\u002Fr\u002Fsteveltn\u002Fhttps-portal\u002F](https:\u002F\u002Fhub.docker.com\u002Fr\u002Fsteveltn\u002Fhttps-portal\u002F)\n\n## Japanese README\n\nThanks to [@yamada28go](https:\u002F\u002Fgithub.com\u002Fyamada28go), there is a [Japanese version of this README](\u002FREADME-ja.md) available. However, due to my inability to understand Japanese, I can't guarantee that the Japanese version is up-to-date.\n\n## About Me  \nI’m a software engineer and an engineering manager with experience in cross-cultural development teams, particularly those with a presence in China. I specialize in bridging communication and culture gaps, optimizing workflows, and ensuring seamless collaboration across borders.  \n\n​**Interested in consulting?**  \nI’m available for tech consulting projects! Whether you need help with team alignment, process improvement, or technical guidance, I’d love to assist. Feel free to contact via [steve.wy.shao+consulting@gmail.com](mailto:steve.wy.shao+consulting@gmail.com) to discuss your needs.  \n\n## Table of Contents\n\n- [HTTPS-PORTAL](#https-portal)\n  - [Prerequisite](#prerequisite)\n  - [See It Work](#see-it-work)\n  - [Quick Start](#quick-start)\n  - [Features](#features)\n    - [Test Locally](#test-locally)\n    - [Redirections](#redirections)\n    - [Automatic Container Discovery](#automatic-container-discovery)\n    - [Hybrid Setup with Non-Dockerized Apps](#hybrid-setup-with-non-dockerized-apps)\n    - [Multiple Domains](#multiple-domains)\n    - [Custom Ports](#custom-ports)\n    - [Multiple Upstreams](#multiple-upstreams)\n    - [Serving Static Sites](#serving-static-sites)\n    - [Share Certificates with Other Apps](#share-certificates-with-other-apps)\n    - [HTTP Basic Auth](#http-basic-auth)\n    - [Access Restriction](#access-restriction)\n    - [Logging configuration](#logging-configuration)\n    - [Debugging](#debugging)\n    - [Other Configurations](#other-configurations)\n    - [Internationalized Domain Names (IDN)](#internationalized-domain-names-idn)\n  - [Advanced Usage](#advanced-usage)\n    - [Configure Nginx through Environment Variables](#configure-nginx-through-environment-variables)\n    - [Change Configuration Dynamically](#change-configuration-dynamically)\n    - [Override Nginx Configuration Files](#override-nginx-configuration-files)\n    - [Manually Set Private Key Length\u002FType](#manually-set-private-key-length-type)\n  - [How It Works](#how-it-works)\n  - [About Rate Limits of Let's Encrypt](#about-rate-limits-of-lets-encrypt)\n  - [Troubleshooting](#troubleshooting)\n  - [Credits](#credits)\n\n## Prerequisite\n\nHTTPS-PORTAL is shipped as a Docker image. To use it, you need a Linux machine\n(either local or remote host) which:\n\n* Has 80 and 443 port available and exposed.\n* Has [Docker Engine](https:\u002F\u002Fdocs.docker.com\u002Fengine\u002Finstallation\u002F) installed.\n  In addition, [Docker Compose](https:\u002F\u002Fdocs.docker.com\u002Fcompose\u002F) is highly\n  recommended, for it makes your life easier. Examples in our documents are\n  mainly in Docker Compose format.\n* Has all domains you're going to use in the following examples resolving to\n  it.\n\nThough it is good to have, knowledge about Docker is not required to use\nHTTPS-PORTAL.\n\n## See It Work\n\nCreate a `docker-compose.yml` file with the following content in any directory\nof your choice:\n\n```yaml\nversion: '3'\n\nservices:\n  https-portal:\n    image: steveltn\u002Fhttps-portal:1\n    ports:\n      - '80:80'\n      - '443:443'\n    environment:\n      DOMAINS: 'example.com'\n      # STAGE: 'production' # Don't use production until staging works\n    volumes:\n      - https-portal-data:\u002Fvar\u002Flib\u002Fhttps-portal\n\nvolumes:\n    https-portal-data: # Recommended, to avoid re-signing when upgrading HTTPS-PORTAL\n```\n\nRun the `docker-compose up` command in the same directory. A moment later you'll\nhave a welcome page running in\n[https:\u002F\u002Fexample.com](https:\u002F\u002Fexample.com).\n\n## Quick Start\n\nHere is a more real-world example: Create the file `docker-compose.yml` in another\ndirectory:\n\n```yaml\nversion: '3'\n\nhttps-portal:\n  image: steveltn\u002Fhttps-portal:1\n  ports:\n    - '80:80'\n    - '443:443'\n  restart: always\n  environment:\n    DOMAINS: 'wordpress.example.com -> http:\u002F\u002Fwordpress:80'\n    # STAGE: 'production' # Don't use production until staging works\n    # FORCE_RENEW: 'true'\n  volumes: \n    - https-portal-data:\u002Fvar\u002Flib\u002Fhttps-portal\n\nwordpress:\n  image: wordpress\n\ndb:\n  image: mariadb\n  environment:\n    MYSQL_ROOT_PASSWORD: '\u003Ca secure password>'\n\nvolumes:\n  https-portal-data:\n```\n\nRun the `docker-compose up -d` command. A moment later you'll get a WordPress\nrunning on [https:\u002F\u002Fwordpress.example.com](https:\u002F\u002Fwordpress.example.com).\n\nIn the example above, only the environment variables under the `https-portal`\nsection are HTTPS-PORTAL specific configurations. This time we added an extra\nparameter `-d`, which will tell Docker Compose to run the apps defined in\n`docker-compose.yml` in the background.\n\nNote: \n\n- `STAGE` is `staging` by default, which results in a test\n(untrusted) certificate from Let's Encrypt.\n- `wordpress` is the hostname of WordPress container within HTTPS-PORTAL container. Usually you can use the service name of your WordPress container.\n\n## Features\n\n### Test Locally\n\nYou can test HTTPS-PORTAL with your application stack locally.\n\n```yaml\nhttps-portal:\n  # ...\n  environment:\n    STAGE: local\n    DOMAINS: 'example.com'\n```\n\nBy doing this, HTTPS-PORTAL will create a self-signed certificate.\nThis certificate is not likely to be trusted by your browser, but you can\nuse it to test your docker-compose file. Make sure it works with your application\nstack.\n\nNote that HTTPS-PORTAL only listens to `example.com`, as you specified in the compose file.\nIn order to make HTTPS-PORTAL respond to your connection, you need to either:\n\n* modify your `hosts` file to have `example.com` resolving to your docker host to 127.0.0.1 (or any other IP address pointing to your Docker host),\n\nor\n\n* set up DNSMasq on your computer\u002Frouter. This method provides more flexibility.\n\nor\n\n* configure `DOMAINS: 'mysite.lvh.me` in `docker-compose.yml` instead of `example.com` (lvh.me is a wildcard DNS entry that resolves any second level name to 127.0.0.1) so than you can access https:\u002F\u002Fmysite.lvh.me.\n\nOnce you are done testing, you can deploy your application stack to the server.\n\n### Redirections\n\nHTTPS-PORTAL support quick setup for redirections.\n\n```yaml\nhttps-portal:\n  # ...\n  environment:\n    DOMAINS: 'example.com => https:\u002F\u002Ftarget.example.com' # Notice it's \"=>\" instead of the normal \"->\"\n```\n\nAll paths will be redirected to the target. E.g. `https:\u002F\u002Fexample.com\u002Ffoo\u002Fbar` will be 307 redirected to `https:\u002F\u002Ftarget.example.com\u002Ffoo\u002Fbar`.\n\nIf you want a permanent redirection, set the environment variable `REDIRECT_CODE=301`.\n\nA common use case is to redirect `www.example.com` to `example.com`. Configure your DNS, make both `www.example.com` and `example.com` resolve to the HTTPS-PORTAL host, and use the following compose:\n\n```yaml\nhttps-portal:\n  # ...\n  environment:\n    DOMAINS: 'www.example.com => https:\u002F\u002Fexample.com' # Notice it's \"=>\" instead of the normal \"->\"\n```\n\n### Automatic Container Discovery\n\n**WARNING: WE STRONGLY RECOMMEND AGAINST USING THIS FEATURE UNLESS ABSOLUTELY NECESSARY** as exposing Docker socket to a container (even with `:ro`) essentially gives the container root access to your host OS. If you insist, verify the source code carefully. [Read more](https:\u002F\u002Fdev.to\u002Fpetermbenjamin\u002Fdocker-security-best-practices-45ih)\n\nHTTPS-PORTAL is capable of discovering other Docker containers running on the\nsame host, as long as the Docker API socket is accessible within the container.\n\nIn order to make it so, launch HTTPS-PORTAL using the following `docker-compose.yml`.\n\n```yaml\nversion: '2'\n\nservices:\n  https-portal:\n    # ...\n    volumes:\n      - \u002Fvar\u002Frun\u002Fdocker.sock:\u002Fvar\u002Frun\u002Fdocker.sock:ro # DANGEROUS, see the warning above\n```\n\nand launch one or more web applications with:\n\n```yaml\nversion: '2'\n\nservices:\n  a-web-application:\n    # ...\n    environment:\n      # tell HTTPS-PORTAL to set up \"example.com\"\n      VIRTUAL_HOST: example.com\n```\n\n**Caveat**: Your web application must be created in the same network as HTTPS-PORTAL.\n\nNote 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 HTTPS-PORTAL.\n\nThis feature allows you to deploy multiple web applications on the same host\nwithout restarting HTTPS-PORTAL itself or interrupting any other application while\nadding\u002Fremoving web applications.\n\nIf your web service has more than one port exposed (mind that ports can be exposed in your web service Dockerfile),\nuse the environment variable `VIRTUAL_PORT` to specify which port accepts HTTP requests:\n\n```yaml\na-multi-port-web-application:\n  # ...\n  expose:\n    - '80'\n    - '8080'\n  environment:\n    VIRTUAL_HOST: example.com\n    VIRTUAL_PORT: '8080'\n```\n\nOf course container discovery works in combination with ENV specified domains:\n\n```yaml\nhttps-portal:\n  # ...\n  volumes:\n    - \u002Fvar\u002Frun\u002Fdocker.sock:\u002Fvar\u002Frun\u002Fdocker.sock:ro # DANGEROUS, see the warning above\n  environment:\n    DOMAINS: 'example.com -> http:\u002F\u002Fupstream'\n```\n\n### Hybrid Setup with Non-Dockerized Apps\n\nWeb applications that run directly on the host machine instead of in Docker\ncontainers are available at `host.docker.internal`. It also works with *Docker for Mac* and *Docker for Windows*.\n\nFor instance, if an application accepts HTTP requests on port 8080 of the host\nmachine, you can start HTTPS-PORTAL by:\n\n```yaml\nhttps-portal:\n  # ...\n  environment:\n    DOMAINS: 'example.com -> http:\u002F\u002Fhost.docker.internal:8080'\n```\n\n#### Firewall settings ####\n\nIf you use a firewall like [ufw](https:\u002F\u002Fhelp.ubuntu.com\u002Fcommunity\u002FUFW), you\nmight need to allow communication from the container to your docker host machine.\nYou can check if ufw is active by executing `ufw status`.\n\nIf the command returns `active`, add the ufw rule to allow communication on port 8080 from HTTPS-PORTAL's container IP to the docker host IP on the port where the web application is reachable:\n\n```\nDOCKER_HOST_IP=`docker network inspect code_default --format='{{ .IPAM.Config}}' |awk '{print $2}'` # Assumes that the network is named code_default\nHTTPS_PORTAL_IP=`docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' code_https-portal_1` # Assumes that the container has the name code_https-portal_1\nufw allow from $HTTPS_PORTAL_IP to $DOCKER_HOST_IP port 8080\n```\n\n### Multiple Domains\n\nYou can specify multiple domains by splitting them with commas:\n\n```yaml\nhttps-portal:\n  # ...\n  environment:\n    DOMAINS: 'wordpress.example.com -> http:\u002F\u002Fwordpress:80, gitlab.example.com -> http:\u002F\u002Fgitlab'\n```\n\nYou can also specify the stage (`local`, `staging`, or `production`) for each individual site, note that stages of individual sites overrides the global stage:\n\n```yaml\nDOMAINS: 'wordpress.example.com -> http:\u002F\u002Fwordpress #local, gitlab.example.com #staging'\n```\n\nIf you have multiple domains, consider using YAML multiline folding operator '>':\n```yaml\nhttps-portal:\n  # ...\n  environment:\n    DOMAINS: >\n      wordpress.example.com -> http:\u002F\u002Fwordpress:80,\n      gitlab.example.com -> http:\u002F\u002Fgitlab\n    OTHER_VARS: ...\n```\n\nIt will make reading and managing multiple domains easier.\n\n### Custom Ports\n\nDue to Let's Encrypt's constraints, Port 80 must be used for verifying the domian. But you can use a different port than 443 for SSL traffic.\n\n```yaml\nhttps-portal:\n  # ...\n  ports:\n    - '80:80'\n    - '4343:4343' # Make sure to add the other ports you want to listen to\n    - '443:443'\n  environment:\n    # You can combine the same domain with different ports.\n    DOMAINS: >\n      wordpress.example.com:4343 -> http:\u002F\u002Fwordpress:80,\n      wordpress.example.com:443 -> http:\u002F\u002Fgitlab:80, \n    OTHER_VARS: ...\n```\n\n### Multiple Upstreams\n\nIt's possible to define multiple upstreams for a domain for the purpose of load-balancing and\u002For HA.\nJust add additional upstreams separated by a pipe separator. Each upstream can have custom parameters.\n\n```yaml\nhttps-portal:\n  # ...\n  environment:\n    DOMAINS: 'wordpress.example.com -> http:\u002F\u002Fwordpress1:80|wordpress2:80[weight=2 max_conns=100]\n```\n\n\nSee [Nginx Upstream-Module](http:\u002F\u002Fnginx.org\u002Fen\u002Fdocs\u002Fhttp\u002Fngx_http_upstream_module.html#server) for possible parameters.\n\n### Serving Static Sites\n\nInstead of forwarding requests to web applications, HTTPS-PORTAL can also serve\n(multiple) static sites directly:\n\n```yaml\nhttps-portal:\n  # ...\n  environment:\n    DOMAINS: 'hexo.example.com, octopress.example.com'\n  volumes:\n    - https-portal-data:\u002Fvar\u002Flib\u002Fhttps-portal\n    - \u002Fdata\u002Fhttps-portal\u002Fvhosts:\u002Fvar\u002Fwww\u002Fvhosts\n```\n\nAfter HTTPS-PORTAL is started, it will create corresponding sub-directories for\neach virtual host in the `\u002Fdata\u002Fhttps-portal\u002Fvhosts` directory on the host machine:\n\n```yaml\n\u002Fdata\u002Fhttps-portal\u002Fvhosts\n├── hexo.example.com\n│  └── index.html\n└── octopress.example.com\n    └── index.html\n```\n\nYou can place your own static files in this directory hierarchy, they will not\nbe overwritten. You need an `index.html` to be served as the homepage.\n\n### Share Certificates with Other Apps\n\nYou can mount an arbitrary host directory to `\u002Fvar\u002Flib\u002Fhttps-portal` as a\n[data volume](https:\u002F\u002Fdocs.docker.com\u002Fengine\u002Fuserguide\u002Fdockervolumes\u002F).\n\nFor instance:\n\n```yaml\nhttps-portal:\n  # ...\n  volumes:\n    - \u002Fdata\u002Fssl_certs:\u002Fvar\u002Flib\u002Fhttps-portal\n```\n\nNow your certificates are available in `\u002Fdata\u002Fssl_certs` on your host.\n\n### HTTP Basic Auth\n\nYou can set up an HTTP Basic Auth easily. It is useful when you put the website\nonline but don't want to open it to public until ready.\n\nIn your docker-compose file:\n\n```yaml\nhttps-portal:\n  # ...\n  environment:\n    DOMAINS: 'username:password@example.com -> \u003Cupstream>'\n```\n\n### Access Restriction\n\n**Notice: Access Restriction might not work as intended with Docker for Mac and Docker for Windows. In those systems, Docker essentially runs in VMs, so the requesting IP would be the IP of the proxy service.**\n\nYou can enable IP access restrictions to protect your website. Specify global restrictions with the environment variable `ACCESS_RESTRICTION`. In addition each website can have individual restrictions.\n\nExample with global restriction:\n\n```yaml\nhttps-portal:\n  # ...\n  environment:\n    ACCESS_RESTRICTION: \"1.2.3.4\u002F24 4.3.2.1\"\n```\n\nExample with individual restrictions:\n\n```yaml\nhttps-portal:\n  # ...\n  environment:\n    DOMAINS: \"[1.2.3.4\u002F24] a.example.com -> \u003Cupstream> , [1.2.3.4\u002F24 4.3.2.1] b.example.com\"\n```\n\nExample for auto discovery:\n\n```yaml\nhttps-portal:\n  # ...\nmy_app:\n  image: ...\n  environment:\n    VIRTUAL_HOST: \"[1.2.3.4] example.com\"\n```\n\nFor valid IP values see [Nginx allow](http:\u002F\u002Fnginx.org\u002Fen\u002Fdocs\u002Fhttp\u002Fngx_http_access_module.html#allow)\n\n### Logging configuration\n\nBy default no Nginx access logs are written, and error logs are written to stdout, which will be captured by Docker. There are few options to configure them:\n\n* Redirect error\u002Faccess logs to stdout\u002Fstderr:\n  \n  ```yaml\n  https-portal:\n    # ...\n    environment:\n      ERROR_LOG: stdout\n      ACCESS_LOG: stderr\n  ```\n\n* Write logs to default locations:\n\n  ```yaml\n  https-portal:\n    # ...\n    environment:\n      ERROR_LOG: default\n      ACCESS_LOG: default\n    volumes:\n      - https-portal-data:\u002Fvar\u002Flib\u002Fhttps-portal\n      - \u002Fpath\u002Fto\u002Flog\u002Fdirectory:\u002Fvar\u002Flog\u002Fnginx\u002F\n      - \u002Fpath\u002Fto\u002Flogrotate\u002Fstate\u002Fdirectory:\u002Fvar\u002Flib\u002Flogrotate\u002F\n  ```\n\n  Default log files pathes are `\u002Fvar\u002Flog\u002Fnginx\u002Faccess.log` and `\u002Fvar\u002Flog\u002Fnginx\u002Ferror.log`.\n\n  Log files within default location `\u002Fvar\u002Flog\u002Fnginx\u002F*.log` are rotated on daily basis.\n  HTTPS-PORTAL will keep up to 30 log files and will compress files older than 2 days\n  (so current day log and previous day log are both available in plain text while all older ones are compresses).\n\n  If you want to alter log rotation configuration, you can overwrite `\u002Fetc\u002Flogrotate.d\u002Fnginx`.\n\n* Write logs to custom locations:\n\n  ```yaml\n  https-portal:\n    # ...\n    environment:\n      ERROR_LOG: \u002Fvar\u002Flog\u002Fcustom-logs\u002Ferror.log\n      ACCESS_LOG: \u002Fvar\u002Flog\u002Fcustom-logs\u002Faccess.log\n    volumes:\n      - https-portal-data:\u002Fvar\u002Flib\u002Fhttps-portal\n      - \u002Fpath\u002Fto\u002Flog\u002Fdirectory:\u002Fvar\u002Flog\u002Fcustom-logs\u002F\n  ```\n\n  Note that no automatic log rotation will be performed in this case.\n\n* Other env variables:\n\n  There are some other configurable environment variables regarding logging:\n\n  * `ACCESS_LOG_BUFFER` - controls buffer size of access log. Example: 16k.\n  * `ERROR_LOG_LEVEL` - controls error log level. Default value is `error`\n\n### Debugging\n\nWith the environment variable `DEBUG=true` you can see more info printed about domain parsing, such as:\n\n```\nDEBUG: name:'example.com' upstreams:'' redirect_target:''\n```\n\n### Other Configurations\n\nBy default, HTTPS-PORTAL renews the certificate about 30 days before the expiry. You can customize it by:\n```\nRENEW_MARGIN_DAYS=30\n```\n\n### Internationalized Domain Names (IDN)\n\nIf you have non-ASCII characters in your domain, [convert it to an ASCII-Compatible Encoding (ACE) form](https:\u002F\u002Fwww.verisign.com\u002Fen_US\u002Fchannel-resources\u002Fdomain-registry-products\u002Fidn\u002Fidn-conversion-tool\u002Findex.xhtml) before using HTTPS-PORTAL.\n\n## Advanced Usage\n\n### Configure Nginx through Environment Variables\n\nIn case you need to change Nginx's default parameters, \nthere are several additional environment variables that you can use to config Nginx.\nThey correspond to the configuration options that you would normally put in `nginx.conf`.\nThe following are the available params with their default values:\n\n```\nINDEX_FILES=index.html                  # A space-separated list of index file names to look for\nWORKER_PROCESSES=1\nWORKER_CONNECTIONS=1024\nKEEPALIVE_TIMEOUT=65\nGZIP=on                                 # can be 'off' (you need quotes)\nSERVER_TOKENS=off\nSERVER_NAMES_HASH_MAX_SIZE=512\nSERVER_NAMES_HASH_BUCKET_SIZE=32        # defaults to 32 or 64 based on your CPU\nCLIENT_MAX_BODY_SIZE=1M                 # 0 disables checking request body size\nPROXY_BUFFERS=\"8 4k\"                    # Either 4k or 8k depending on the platform\nPROXY_BUFFER_SIZE=\"4k\"                  # Either 4k or 8k depending on the platform\nRESOLVER=\"Your custom solver string\"\nPROXY_CONNECT_TIMEOUT=60;\nPROXY_SEND_TIMEOUT=60;\nPROXY_READ_TIMEOUT=60;\nACCESS_LOG=off;\nACCESS_LOG_INCLUDE_HOST=off;            # include vhost in access log (useful for goaccess => use log-format=VCOMBINED)\nREDIRECT_CODE=307                       # Was 301 by default until 1.20.1\n```\n\n#### Websocket\n\nYou can add\n\n```\nWEBSOCKET=true\n```\n\nto make HTTPS-PORTAL proxy WEBSOCKET connections.\n\n#### DNS caching\n\nTo avoid nginx DNS caching, activate dynamic upstream\n\n```\nRESOLVER=\"127.0.0.11 ipv6=off valid=30s\"\nDYNAMIC_UPSTREAM=true\n```\n\n#### HSTS Header\n\nYou can use the follow environment variable to set HSTS header.\n\n**WARNING:** Please test with a low value before you set it to a desired high max_age value. Once you send the header out, all visited clients would refuse to downgrade to HTTP. It would then be impossible to fallback your website to HTTP. \n\n```\nHSTS_MAX_AGE=60  # in seconds\n```\n\n#### IPv6 connectivity\n\n**Notice:** IPv6 is only supported on Linux hosts.\n\nYou can enable IPv6 connection using the following variable:\n\n```\nLISTEN_IPV6=true\n```\n#### Other server block level configurations\n\nYou can add additional `server` block level configurations to each domain:\n\n```yaml\n  environment:\n    ...\n    CUSTOM_NGINX_SERVER_CONFIG_BLOCK: add_header Strict-Transport-Security \"max-age=60\" always;\n```\nYou can also make it multi-line:\n\n```yaml\n  environment:\n    ...\n    CUSTOM_NGINX_SERVER_CONFIG_BLOCK: |\n    \tadd_header Strict-Transport-Security \"max-age=60\" always;\n    \tauth_basic \"Password\";\t\n```\nWhen using variables, you need to escape them with $:\n\n```yaml\n  environment:\n    ...\n    CUSTOM_NGINX_GLOBAL_HTTP_CONFIG_BLOCK: |\n        limit_req_zone $$binary_remote_addr zone=one:10m rate=1000r\u002Fm;\n```\n\nThe `CUSTOM_NGINX_SERVER_CONFIG_BLOCK` will be inserted after all other configuration blocks listed in section \"Configure Nginx through Environment Variables\", and it might conflict with other configurations.\n\nIn addition to the global `CUSTOM_NGINX_SERVER_CONFIG_BLOCK`, which applies to all configurations, there are `CUSTOM_NGINX_\u003CUPPERCASE_AND_UNDERSCORED_DOMAIN_NAME>_CONFIG_BLOCK`s, which are inserted after the `CUSTOM_NGINX_SERVER_CONFIG_BLOCK`, but only into the configuration file for a specific site. **For instance**, To make specific changes to `example.com` only, create an environment variable `CUSTOM_NGINX_EXAMPLE_COM_CONFIG_BLOCK`.\n\n```\n# generated Nginx config:\nserver {\n\tlisten 443 ssl;\n\t... # (other configurations)\n\t\u003C%= CUSTOM_NGINX_SERVER_CONFIG_BLOCK %>\n\t\u003C%= CUSTOM_NGINX_\u003CDOMAIN_NAME>_CONFIG_BLOCK %>\n\tlocation \u002F {\n\t\t...\n\t}\n}\n```\n\nThe variables `CUSTOM_NGINX_GLOBAL_HTTP_CONFIG_BLOCK` and `CUSTOM_NGINX_SERVER_PLAIN_CONFIG_BLOCK` can be used to add your own Nginx statements to the global `http` block or to the plaintext (non-SSL) `server` blocks.\n\nIn the rare case that you want to change the handling of `\u002F.well-known\u002Facme-challenge\u002F` requests, setting `ACME_CHALLENGE_BLOCK` will override the default configuration. Check out the [Nginx config templates](https:\u002F\u002Fgithub.com\u002FSteveLTN\u002Fhttps-portal\u002Ftree\u002Fmaster\u002Ffs_overlay\u002Fvar\u002Flib\u002Fnginx-conf) for more details.\n\n### Change Configuration Dynamically\n\nEnvironment variables may be dynamically overridden by modifying files\n`\u002Fvar\u002Flib\u002Fhttps-portal\u002Fdynamic-env`. The file's name and contents will create\nan environment variable with that name and contents, respectively. About 1s\nafter the last modification, the configuration will be updated to reflect the\nnew configuration. This allows modifying the configuration without downtime.\n\n### Override Nginx Configuration Files\n\nYou can override default nginx settings by providing a config segment of\nnginx.conf containing a valid `server` block. The custom nginx configurations\nare [ERB](http:\u002F\u002Fwww.stuartellis.eu\u002Farticles\u002Ferb\u002F) templates and will be\nrendered before usage.\n\nYou can either just override one single site's config or all sites' configs.\n\n#### Override just one single site's config\n\nIn this case, you provide `\u003Cyour-domain>.conf.erb` and `\u003Cyour-domain>.ssl.conf.erb`. The former one takes care of the ownership verification from Let's Encrypt, and redirection to https URL. The latter one handles https connections.\n\nFor instance, to override both HTTPS and HTTP settings for `my.example.com`,\nyou can launch HTTPS-PORTAL by:\n\n```yaml\nhttps-portal:\n  # ...\n  volumes:\n    - https-portal-data:\u002Fvar\u002Flib\u002Fhttps-portal\n    - \u002Fpath\u002Fto\u002Fhttp_config_file:\u002Fvar\u002Flib\u002Fnginx-conf\u002Fmy.example.com.conf.erb:ro\n    - \u002Fpath\u002Fto\u002Fhttps_config_file:\u002Fvar\u002Flib\u002Fnginx-conf\u002Fmy.example.com.ssl.conf.erb:ro\n```\n\n[This file](\u002Ffs_overlay\u002Fvar\u002Flib\u002Fnginx-conf\u002Fdefault.conf.erb) and [this file](\u002Ffs_overlay\u002Fvar\u002Flib\u002Fnginx-conf\u002Fdefault.ssl.conf.erb) are the default configuration files used by HTTPS-PORTAL.\nYou can probably start by copying these files. You can either keep the variables or just hard-code the domain and upstream, etc.\n\nAnother example can be found [here](\u002Fexamples\u002Fcustom_config).\n\n#### Override All sites' default config\n\nIf you want to make an Nginx configuration that will be used by all sites, you can overwrite `\u002Fvar\u002Flib\u002Fnginx-conf\u002Fdefault.conf.erb` or `\u002Fvar\u002Flib\u002Fnginx-conf\u002Fdefault.ssl.conf.erb`. These two files will be propagated to each site if the site-specific configuration files are not provided.\n\nSince the config files will be used on all your sites, please keep using the variables already in the file and don't hard-code anything.\n\n### Manually Set Private Key Length\u002FType\n\nBy default, HTTPS-PORTAL generate `2048` bits long RSA private key.  \nHowever, you can manually set RSA private key length (`numbits` of `openssl genrsa` command) through `NUMBITS` environment variable.\n\n```yaml\nhttps-portal:\n  # ...\n  environment:\n    NUMBITS: '4096'\n```\n\nAlternatively, you can set the `CERTIFICATE_ALGORITHM` environment variable to `prime256v1`, as [recommended by Mozilla](https:\u002F\u002Fwiki.mozilla.org\u002FSecurity\u002FServer_Side_TLS#Modern_compatibility). Note however, that this setting prevents some older clients\u002Fsystems from connecting.\n\nBoth settings apply to newly generated keys only. If you would like to update existing keys, remove the existing keys stored under `\u002Fvar\u002Flib\u002Fhttps-portal` and restart `https-portal`.\n\n## How It Works\n\nIt:\n\n* obtains an SSL certificate for each of your subdomains from\n  [Let's Encrypt](https:\u002F\u002Fletsencrypt.org).\n* configures Nginx to use HTTPS (and force HTTPS by redirecting HTTP to HTTPS)\n* sets up a cron job that checks your certificates every week, and renew them.\n  if they expire in 30 days.\n\n## About Rate Limits of Let's Encrypt\n\nLet's Encrypt's service is rate limited to ensure fair usage. Please familiarize\nyourself with [the various rate\nlimits](https:\u002F\u002Fletsencrypt.org\u002Fdocs\u002Frate-limits\u002F). This documentation page is\nthe authoritative source for the current rate limit values.\n\nFor most people the most important rate limits are:\n\n* 5 failed validation attempts per hour\n* 50 certificates per registered domain per week\n* 5 duplicated certificate per week (for renewal)\n\nIf you want to use HTTPS for multiple sub-domains with a single certificate\nLet's Encrypt supports putting up to 100 domains in one certificate, however it\ncan require careful planning and is hard to automate. So in HTTPS-PORTAL we only\ndeal with single domain name certificates.\n\nHTTPS-PORTAL stores your certificates in a data volume and will not re-sign\ncertificates until 30 days before expiration if a valid certificate is found\n(you can force renew certificates by using `FORCE_RENEW: 'true'` environment\nvariable).  However if you play around with the image a lot, you can hit the\nlimit. That's why `STAGE` is `staging` by default, and thus we use the\nLet's Encrypt staging server. When you have finished your experiments and feel\neverything is good, you can switch to production mode with `STAGE:\n'production'`.\n\n## Troubleshooting\n\n### Force renew\n\nIf you find your certificates are not chained correctly, please run the container\nagain with the follow setting once:\n\n```yaml\nhttps-portal:\n  # ...\n  environment:\n    # ...\n    FORCE_RENEW: 'true' # \u003C-- here\n```\n\nThis is because with ACME v2 returns the full chain instead of a partial chain \nwith ACME v1. If you have old certificates stored, HTTPS-PORTAL may not be able \nto handle the case correctly. If you run into this issue, just `FORCE_RENEW` to \nobtain a new set of certificates.\n\n### Reset the data volume\n\nIf you find HTTPS-PORTAL is not behaving as expected, try to reset the data volume:\n\n```\ndocker-compose down\ndocker volume ls -q | grep https-portal-data # Delete the volume used by HTTPS-PORTAL\ndocker-compose up\n```\n\n## Credits\n\n* [acme-tiny](https:\u002F\u002Fgithub.com\u002Fdiafygi\u002Facme-tiny) by Daniel Roesler.\n* [docker-gen](https:\u002F\u002Fgithub.com\u002Fjwilder\u002Fdocker-gen) by Jason Wilder.\n* [s6-overlay](https:\u002F\u002Fgithub.com\u002Fjust-containers\u002Fs6-overlay).\n","HTTPS-PORTAL 是一个基于 Nginx、Let's Encrypt 和 Docker 的全自动 HTTPS 服务器。它能够自动获取和更新 Let's Encrypt 提供的 SSL 证书，只需一行额外配置即可为任何现有 Web 应用启用 HTTPS 服务。项目采用 Ruby 编写，支持多种高级功能如自动容器发现、多域名支持以及静态站点服务等，极大简化了 HTTPS 部署过程。适用于需要快速安全地将应用部署到互联网上的场景，特别适合于使用 Docker 进行开发和部署的团队或个人。",2,"2026-06-11 03:14:11","top_language"]