{"id":18493385,"url":"https://github.com/netfloex/nginx","last_synced_at":"2026-02-25T09:34:08.375Z","repository":{"id":37781299,"uuid":"382597169","full_name":"Netfloex/Nginx","owner":"Netfloex","description":"A docker container to simplify the process of creating Nginx configs.","archived":false,"fork":false,"pushed_at":"2023-01-14T19:52:30.000Z","size":468,"stargazers_count":3,"open_issues_count":1,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-23T18:52:03.742Z","etag":null,"topics":["cloudflare","cloudflare-dns","docker","docker-compose","docker-container","docker-image","nginx","nginx-configuration","nginx-docker","nginx-module","nginx-proxy","proxy","typescript","yarn"],"latest_commit_sha":null,"homepage":"https://hub.docker.com/r/netfloex/nginx","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Netfloex.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-07-03T11:21:36.000Z","updated_at":"2022-09-13T22:28:10.000Z","dependencies_parsed_at":"2023-02-09T20:30:57.359Z","dependency_job_id":null,"html_url":"https://github.com/Netfloex/Nginx","commit_stats":null,"previous_names":[],"tags_count":11,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Netfloex%2FNginx","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Netfloex%2FNginx/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Netfloex%2FNginx/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Netfloex%2FNginx/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Netfloex","download_url":"https://codeload.github.com/Netfloex/Nginx/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247939819,"owners_count":21021855,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cloudflare","cloudflare-dns","docker","docker-compose","docker-container","docker-image","nginx","nginx-configuration","nginx-docker","nginx-module","nginx-proxy","proxy","typescript","yarn"],"created_at":"2024-11-06T13:14:12.617Z","updated_at":"2026-02-25T09:34:03.339Z","avatar_url":"https://github.com/Netfloex.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"## Nginx Config Manager\n\nThis docker container makes it a lot easier to manage Nginx configs.\n\nInstead of creating an entire new file with a lot of boilerplate you can just easily add a new line to the config.\nNginx Config Manager will create the Nginx config for you, and automatically requests certificates for it using certbot.\nIt will also create Diffie-Hellman parameters, this could take a while when the container launches for the first time.\nIf you use cloudflare, it can also automatically restore your visitor ip addresses. (See [Cloudflare](#cloudflare-real-ip))\n\n## Installation\n\nThis version uses `nginx:stable-alpine` as a parent container. This allows it to reload nginx by itself.\nIf you would like to have a standalone version see [#standalone](#standalone)\n\n[docker-compose.example.yml](docker-compose.example.yml):\n\nThe only required change is `CERTBOT_EMAIL`.\n\n[Click Here](#environment-options) for a list of Environment Options.\n\n```yaml\nversion: \"3.3\"\n\nservices:\n    nginx:\n        image: netfloex/nginx:v2.4.0\n        container_name: nginx\n        environment:\n            CERTBOT_EMAIL: EMAIL # Required\n        ports:\n            - 80:80\n            - 443:443\n        volumes:\n            #  Optional\n\n            # - ./logs:/var/log/nginx\n            # - ./nginx_config_files:/etc/nginx/conf.d\n            - ./data:/app/data # Needed when using custom files or cloudflare, this is used as a cache.\n\n            # Required\n\n            - ./letsencrypt:/etc/letsencrypt\n            - ./config:/app/config\n```\n\nYou can create a config file using json5, js or yaml.\nThe file should be placed in the config folder as `config.(yml|yaml|json|jsonc|json5|js)`\n\n\u003ca href=\"config/config.example.js\"\u003e\n\u003cimg src=\"https://img.shields.io/badge/Example-javascript-yellow\" alt=\"javascript\"\u003e\n\u003c/a\u003e\n\u003ca href=\"config/config.example.jsonc\"\u003e\n\u003cimg src=\"https://img.shields.io/badge/Example-JSON-green\" alt=\"json\"\u003e\n\u003c/a\u003e\n\u003ca href=\"config/config.example.yml\"\u003e\n\u003cimg src=\"https://img.shields.io/badge/Example-YAML-red\" alt=\"yaml\"\u003e\n\u003c/a\u003e\n\nPick your favorite language to write your config in and create a file like \"config/config.yml\"\n\nSimple Example:\n\n```js\nmodule.exports = {\n\tcloudflare: true, // When using Cloudflare\n\tservers: {\n\t\t\"example.com\": {\n\t\t\tproxy_pass: \"http://mysite:3000\",\n\t\t\tsubdomains: {\n\t\t\t\twww: \"http://mysite:3000\" // Converts to www.example.com\n\t\t\t}\n\t\t}\n\t}\n};\n```\n\nThe above example could be shorter:\n\n```js\nmodule.exports = {\n\tcloudflare: true, // When using Cloudflare\n\tservers: {\n\t\t\"example.com\": \"http://mysite:3000\",\n\t\t\"www.example.com\": \"http://mysite:3000\"\n\t}\n};\n```\n\nThis example fetches [the latest ips from Cloudflare](#cloudflare-real-ip), enables SSL with Certbot, creates DH-Params, and creates two config files:\n\n```\n    example.com  \u003e  http://mysite:3000\nwww.example.com  \u003e  http://mysite:3000\n```\n\nA more complete example can be found [here](config/config.example.js).\n\n### Good to Know\n\nThe entire config is located in one file.\n\nAll properties are optional.\n\nThe config is validated by [zod](https://github.com/colinhacks/zod), so you know when you make mistakes.\n\nIf you only need a proxy pass you can shorten it:\n\nInstead of writing:\n\n```js\n/* servers: */ {\n\t\"example.com\": {\n\t\tproxy_pass: \"http://base_domain:80\"\n\t}\n}\n```\n\nYou can also write:\n\n```js\n/* servers: */ {\n\t\"example.com\": \"http://base_domain:80\"\n}\n```\n\n## Reloading config\n\nThe config can be reloaded by sending a SIGHUP signal to the container.\nThis updates Nginx's configuration files and renews certificates if needed.\n\nWhen running inside docker:\n\n```bash\ndocker kill --signal=HUP nginx_config_manager\n```\n\n## Variable Substitution\n\nYou can use environment variables in your config by using `%env:VARIABLE%`, where `VARIABLE` is your variable.\n\n\u003e Note: currently this is only possible when using JSON \\\n\u003e Tip: If your using js, you can also use `process.env`\n\n```conf\n# environment variables\nUSERNAME=John\nPASSWORD=Doe\n```\n\n```jsonc\n// config.json\n/* Server/Subdomain/Location: */ {\n\t// Single user\n\t\"auth\": {\n\t\t\"username\": \"%env:USERNAME%\", // \"John\"\n\t\t\"password\": \"%env:PASSWORD%\" // \"Doe\"\n\t}\n}\n```\n\n[Code](src/utils/parseUserConfig.ts)\n\n## Server Options\n\n-   [Proxy Pass](#proxy-pass)\n-   [Custom CSS](#custom-css)\n-   [Custom JS](#custom-js)\n-   [Websocket](#websocket)\n-   [Headers](#headers)\n-   [Cors](#cors)\n\n-   [Return](#return)\n-   [HTML](#html)\n-   [Redirect](#redirect)\n-   [Rewrite](#rewrite)\n-   [Static Files](#static-files)\n\n-   [Basic Auth](#basic-auth)\n-   [Location Blocks](#location-blocks)\n\n## Global Options\n\n-   [Cloudflare Real IP](#cloudflare-real-ip)\n-   [Access Log Format](#accesslog-format)\n\n## Options\n\nThis is a list of options possible inside a (sub)domain or location.\n\n### Proxy Pass\n\nProxies the request to another location.\n\nWhen the container starts a DNS Lookup is performed to test if the hostname is valid.\nTo disable this see [Environment Options](#environment-options)\n\n```js\n/* Server/Subdomain/Location: */ {\n\tproxy_pass: \"http://hostname:80\";\n}\n```\n\n[Code](src/lib/createConfig.ts)\n\n### Custom CSS\n\nThis adds a custom CSS file to an application.\nIt should be a url to a CSS file.\n\nThis file is downloaded and compressed, its then stored inside `/app/custom/css` [Configurable](#paths).\n\nThe compressed CSS is then appended to the end of the `\u003chead\u003e` by using Nginx's `sub_filter`.\n\n```js\n/* Server/Subdomain/Location: */ {\n\tcustom_css: \"http://example.com/style.css\"; // The use of an array is possible too\n}\n```\n\nIt will add the following directives:\n\n```conf\n# Don't sent this header to the proxy\nproxy_set_header Accept-Encoding \"\";\nsub_filter '\u003c/head\u003e' '\u003clink rel=\"stylesheet\" type=\"text/css\" href=\"/custom_assets/css/**.css\"\u003e\u003c/head\u003e';\nsub_filter_once on;\n```\n\n\u003e Source [theme-park.dev](https://docs.theme-park.dev/setup/#nginx)\n\n[Code](src/utils/downloadCSS.ts)\n\n### Custom JS\n\nThis allows to use a custom JS file.\nIt should be a url to a JS file.\n\nThis file is downloaded, its then stored inside `/app/custom/js` [Configurable](#paths).\n\nThis file is appended to the end of the `\u003cbody\u003e` by using Nginx's `sub_filter`.\n\n```js\n/* Server/Subdomain/Location: */ {\n\tcustom_js: \"http://example.com/script.js\"; // The use of an array is possible too\n}\n```\n\nIt will add the following directives:\n\n```conf\n# Don't sent this header to the proxy\nproxy_set_header Accept-Encoding \"\";\nsub_filter '\u003c/body\u003e' '\u003cscript src=\"/custom_assets/js/**.js\"\u003e\u003c/script\u003e\u003c/body\u003e';\nsub_filter_once on;\n```\n\n\u003e Source [theme-park.dev](https://docs.theme-park.dev/setup/#nginx)\n\n[Code](src/utils/downloadJSToFile.ts)\n\n### Websocket\n\nOption to enable Websocket support, this adds the following to the config:\n\n```conf\nproxy_set_header Upgrade $http_upgrade;\nproxy_set_header Connection $http_connection;\nproxy_http_version 1.1;\n```\n\nExample:\n\n```js\n/* Server/Subdomain/Location: */ {\n\twebsocket: true; // Default: false\n}\n```\n\n[Code](src/lib/createConfig.ts)\n\n### Headers\n\nAllows adding headers to the response.\n\nExpects an object with key values of the headers.\n\n\u003e These headers are sent to the client\n\n```js\n/* Server/Subdomain/Location: */ {\n\theaders: {\n\t\t\"Content-Type\": \"text/html\",\n\t\t\"x-powered-by\": \"overridden\"\n\t};\n}\n```\n\n[Code](src/lib/createConfig.ts)\n\n### Cors\n\nAdds a `Access-Control-Allow-Origin` header with the supplied value.\n\nExpects an url, or `true`/`*` to allow any origin.\n\n[Code](src/lib/parseConfig.ts)\n\n### Return\n\nThis may be useful to show a custom message with a custom status code.\n\nThis is equivalent to Nginx's [return](https://nginx.org/en/docs/http/ngx_http_rewrite_module.html#return)\n\n```js\n/* Server/Subdomain/Location: */ {\n\t\"return\": `404 \"Not found\"`,\n\theaders: {\n\t\t\"Content-Type\": \"text/html\",\n\t\t\"x-powered-by\": \"overridden\"\n\t};\n}\n```\n\n[Code](src/lib/createConfig.ts)\n\n### HTML\n\nFor displaying simple HTML.\nThis is equivalent to `\"return\": `200 \"Message\"``\n\n```js\n/* Server/Subdomain/Location: */ {\n\t\"html\": \"\u003ch1\u003eHello World\u003c/h1\u003e\"\n}\n```\n\n[Code](src/lib/createConfig.ts)\n\n### Redirect\n\nRedirect to another location\n\n```js\n/* Server/Subdomain/Location: */ {\n\tredirect: \"/new_location\";\n}\n```\n\n[Code](src/lib/createConfig.ts)\n\n### Rewrite\n\nAllows for complex redirects, the redirect only happens if the first argument matches.\n\nThis is equivalent to Nginx's [rewrite](https://nginx.org/en/docs/http/ngx_http_rewrite_module.html#rewrite)\n\n\u003e Note: If possible redirect/return should be used.\n\n```js\n/* Server/Subdomain/Location: */ {\n\trewrite: \"^/users/(.*)$ /users?id=$1\"; // Redirects /users/test to /users?id=test\n}\n```\n\n[Code](src/lib/createConfig.ts)\n\n### Static Files\n\nAllows hosting static files, same as [root](https://nginx.org/en/docs/http/ngx_http_core_module.html#root)\nWhen not using an absolute path it's relative to `/app`\n\n```js\n/* Server/Subdomain/Location: */ {\n\tstatic: \"site\"; // Resolves to /app/site\n}\n```\n\nDocker Compose\n\n```yaml\nvolumes:\n    - ./site:/app/site\n```\n\n### Basic Auth\n\nEnables authorization for a page\n\nExpects an object with username and password. Can also be an array for multiple users.\n\nThe password is hashed using Apache's apr1 md5 algorithm. A .htpasswd file is created and stored inside $DATA/auth\n\n\u003e Tip: If you don't want your password visible inside the config use [Variable Substitution](#variable-substitution)\n\n```js\n/* Server/Subdomain/Location: */ {\n\t// Single user\n\tauth: {\n\t\tusername: \"user\",\n\t\tpassword: \"pass\"\n\t},\n\n\t// Shorthand for using default username (admin by default)\n\tauth: \"password\",\n\n\t// Multiple Users\n\tauth: [\n\t\t{\n\t\t\tusername: \"bob\",\n\t\t\tpassword: \"hi\"\n\t\t},\n\t\t{\n\t\t\tusername: \"other\",\n\t\t\tpassword: \"user\"\n\t\t}\n\t]\n};\n```\n\nIf you do not specify the username the default will be used (admin), to change this edit:\n\n```js\n/* Config: */ {\n\tusername: \"bob\"\n\tservers: {\n\t\t\"example.com\": {\n\t\t\tproxy_pass: \"http://example\",\n\t\t\tauth: \"password\" // Username is bob\n\t\t}\n\t}\n}\n```\n\n[Code](src/utils/createAuthFile.ts)\n\n---\n\n### Location Blocks\n\n```js\n/* Server/Subdomain: */ {\n\tlocation: {\n\t\t\"/custom/path\": {\n\t\t\tproxy_pass: \"http://proxy_pass:80\",\n\n\t\t\t// Any other option...\n\t\t\tcustom_css: \"http://example.com/style.css\"\n\t\t}\n\t}\n}\n```\n\nor simplified:\n\n```js\n/* Server/Subdomain: */ {\n\tlocation: {\n\t\t\"/custom/path\": \"http://proxy_pass:80\"\n\t}\n}\n```\n\n[Code](src/lib/createConfig.ts)\n\n### Cloudflare Real IP\n\nRetrieves [Cloudflare's ips](https://api.cloudflare.com/client/v4/ips) and creates a Nginx config to trust their `CF-Connecting-IP` header as a source for a visitors real ip.\n\nBy default this data is cached for 7 days. [Edit](#cloudflare-cache-duration)\n\nCurrently this only updates when the container starts.\n\n```js\n// config.js\nmodule.exports = {\n\tcloudflare: true,\n\tservers: {}\n};\n```\n\n[Code](src/utils/enableCloudflare.ts)\n\n### Access Log Format\n\nThis allows customizing the access log format.\nFor variables see [here](https://nginx.org/en/docs/varindex.html)\n\n```js\n// config.js\nmodule.exports = {\n\tnginx: {\n\t\tlog: \"$time_local $remote_addr\"\n\t}\n};\n```\n\n[Code](src/utils/editNginxConfig.ts)\n\n## Environment Options\n\n#### Don't Check Hosts\n\nFor every `proxy_pass`'s hostname a DNS lookup is performed to test if it can be found in upstream.\n\nIf the dns lookup fails the container exits with an error: `Could not resolve: host`.\nThis check is useful because otherwise Nginx will exit later.\n\nTo disable this check, set the following variable:\n\n```bash\nDONT_CHECK_HOSTS=\"true\" # Default: false\n```\n\n#### Allow unresolved hosts\n\nWhen nginx encounters a `proxy_pass` directive it does a DNS lookup.\nIf this fails Nginx will exit / wont start.\n\nTo allow starting you can set:\n\n```bash\nDONT_EXIT_NO_UPSTREAM=\"true\" # Default: false\n```\n\n#### Don't download custom files\n\nDisables the actual downloading of the files specified using `custom_css` or `custom_js`.\n\nMainly useful for testing in [this workflow](.github/workflows/main.yml)\n\n```bash\nDONT_DOWNLOAD_FILES=\"true\" # Default: false\n```\n\n#### Cloudflare Cache Duration\n\nThe [Cloudflare Option](#cloudflare-real-ip) caches the list of ip addresses.\nBy default for 7 days.\nTo customize this duration set the following variable in milliseconds:\n\n```bash\nCLOUDFLARE_CACHE_DURATION=\"2419200000\" # Default: 604800000\n```\n\n#### Diffie-Hellman parameter size\n\nThe default size is 2048, which should be secure enough.\nIf you make this value larger it will take longer to create.\n\n\u003e Note: if you want to change the size, you should also delete your old dhparam.pem otherwise it won't be recreated.\n\n```bash\nDHPARAM_SIZE=\"2048\"\n```\n\n#### Disable Certbot\n\nIf you have a domain without or with expired certificates this container will request certificates for that domain.\n\nTo disable this you can set the following:\n\n```bash\nDISABLE_CERTBOT=\"true\"\n```\n\n#### Enable config without certificates\n\nA domain without certificates will not be created (because Nginx will throw an error on launch)\n\nIf you would like to create configs even when it has missing certificate files:\n\n```bash\nENABLE_CONFIG_MISSING_CERTS=\"true\"\n```\n\n#### Certbot Email (Required)\n\nThis email is used to request certificates using certbot.\nLetsencrypt will send you an email when a certificate expires soon.\nIn the future an option will be added to register without email using certbot's `--register-unsafely-without-email`. More info [here](https://eff-certbot.readthedocs.io/en/stable/using.html#certbot-command-line-options)\n\n```bash\nCERTBOT_EMAIL=\"email@example.com\"\n```\n\n#### Letsencrypt Staging environment\n\nWhen using Letsencrypt's production environment to test things out, there is a high chance you will be running against rate limits.\n\nIn order to use the [staging environment](https://letsencrypt.org/docs/staging-environment/):\n\n```bash\nSTAGING=\"true\"\n```\n\n#### ECDSA or RSA certificates\n\nBy default the container requests ECDSA certificates, which uses a newer encryption algorithm than RSA certificates.\n\nIf you still want RSA certificates:\n\n\u003e Note: You might need to wait until your certificates expire in order to replace them automatically.\n\n```bash\nUSE_ECDSA=\"false\"\n```\n\n#### Watch config file\n\nWatches the config file for changes, and live reloads when it changes.\n\n\u003e Currently this can only be used with the standalone image\n\u003e Because the node process wil run forever so nginx won't be started\n\n```bash\nWATCH_CONFIG_FILE=\"true\"\n```\n\n#### Log formatting\n\nBy default the log is formatted so every message starts at the same width.\n\nIf you want to disable the adding of spaces you can disable this by setting:\n\n```bash\nLOG_FORMAT_COLUMNS=\"false\"\n```\n\n#### Disable log elements\n\nIf you would like to disable certain elements in the log messages you can:\n\n| 0.100s | [NCM] | [INFO] | [CONFIG] | Config is valid |\n| ------ | ----- | ------ | -------- | --------------- |\n| Time   | Name  |        | Tag      |                 |\n\n```bash\nLOG_SHOW_TIME=\"false\"\nLOG_SHOW_NAME=\"false\"\nLOG_SHOW_TAG=\"false\"\n```\n\n#### Paths\n\nAll values are set to there default, the commented value is the path inside the container.\n\nYou can update each path by setting the environment variable\n\n```bash\n# The config folder\nCONFIG_PATH=\"./config\" # /app/config\n\n# If you want to point to a specific file instead of a folder\nCONFIG_FILE= # Unset\n\n\n\n# Nginx folder\nNGINX_PATH=\"./nginx\" # /etc/nginx\n\n# Generated configs folder\nNGINX_CONFIG_PATH=\"$NGINX_PATH/conf.d\" # /etc/nginx/conf.d\n\n# The cloudflare ip list config path\nCLOUDFLARE_CONFIG_PATH=\"$NGINX_CONFIG_PATH/cloudflare.conf\" # /etc/nginx/conf.d/cloudflare.conf\n\n\n\n# Letsencrypt directory\nLETSENCRYPT_PATH=\"/etc/letsencrypt\"\n\n# Diffie-Hellman file\nDHPARAM_PATH=\"$LETSENCRYPT_PATH/dhparams/dhparams.pem\" # /etc/letsencrypt/dhparams/dhparams.pem\n\n\n\n# Data location, cloudflare ip cache, custom files and auth files\nDATA_PATH=\"./data\" # /app/data\n\n# Stores custom files: CSS \u0026 JS\nCUSTOM_FILES_PATH=\"$DATA_PATH/custom\" # /app/data/custom\n\n# Stores auth files, Stores the username:hashed_password\nAUTH_PATH=\"$DATA_PATH/auth\" # /app/data/auth\n\n# Stores a cache of the cloudflare ip list.\nSTORE_PATH=\"$DATA_PATH/store.json\" # /app/data/store.json\n```\n\n[Code](src/utils/settings.ts)\n\n# Standalone\n\nYou can also run this container without Nginx builtin.\n\n\u003e Keep in mind that this also means that NCM won't be able to reload nginx.\n\n\u003e So you will have to this manually by running `docker exec nginx nginx -s reload` each time new configs are created\n\nIf you want you let NCM watch your config file for changes [see here](#watch-config-file)\n\nIn order to do so see this [Docker Compose](docker-compose.standalone.yml)\n\n## Old Parent Image\n\nIn older versions this container used [JonasAlfredsson/docker-nginx-certbot](https://github.com/JonasAlfredsson/docker-nginx-certbot) as a parent container.\nSince version v2.0.0 most of it's features like requesting certificates and generating Diffie-Hellman parameters are now included in this container.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnetfloex%2Fnginx","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnetfloex%2Fnginx","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnetfloex%2Fnginx/lists"}