{"id":13415961,"url":"https://github.com/roquie/smalte","last_synced_at":"2025-04-08T22:30:56.400Z","repository":{"id":45566972,"uuid":"149743631","full_name":"roquie/smalte","owner":"roquie","description":"Dynamically configure applications that require static configuration in docker container.","archived":false,"fork":false,"pushed_at":"2021-12-08T06:44:04.000Z","size":13,"stargazers_count":32,"open_issues_count":1,"forks_count":5,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-07-31T21:54:49.477Z","etag":null,"topics":["clang","docker","envsubst","nim","nim-lang","smalte","template"],"latest_commit_sha":null,"homepage":"","language":"Nim","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/roquie.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":"2018-09-21T09:44:42.000Z","updated_at":"2024-07-02T00:26:01.000Z","dependencies_parsed_at":"2022-08-26T21:09:49.573Z","dependency_job_id":null,"html_url":"https://github.com/roquie/smalte","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/roquie%2Fsmalte","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/roquie%2Fsmalte/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/roquie%2Fsmalte/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/roquie%2Fsmalte/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/roquie","download_url":"https://codeload.github.com/roquie/smalte/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247939929,"owners_count":21021873,"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":["clang","docker","envsubst","nim","nim-lang","smalte","template"],"created_at":"2024-07-30T21:00:53.318Z","updated_at":"2025-04-08T22:30:51.392Z","avatar_url":"https://github.com/roquie.png","language":"Nim","funding_links":[],"categories":["Container Operations","Template engine","Nim","Text Processing","Web","nim","Running Containers"],"sub_categories":["Container Composition","Template Engines","Composition"],"readme":"Smalte\n======\n\n[![CircleCI](https://circleci.com/gh/roquie/smalte.svg?style=svg)](https://circleci.com/gh/roquie/smalte)\n[![GitHub tag](https://img.shields.io/github/tag/roquie/smalte.svg)](https://github.com/roquie/smalte)\n[![GitHub](https://img.shields.io/github/license/roquie/smalte.svg)](https://github.com/roquie/smalte/blob/master/LICENSE)\n\nSmalte – is a **smal**l **t**emplate **e**ngine. Dynamically configure applications that require static configuration in docker container. This is best replacement for envsubst. [Example of usage](https://github.com/roquie/docker-php-webapp/blob/master/conf/start.sh#L28).\n\nWritten in [nim-lang](https://nim-lang.org) and compiled to C. Fast. Binary size (197kb).\n\n## TL;DR\n\nReplaces env variables with values from global system scope:\n\n```bash\nsmalte build /etc/nginx/nginx_spa.conf.tmpl:/etc/nginx/nginx_spa.conf\n```\n\n## Why?\n\nIf you using `envsubst` utility for dynamically configure the application, you have to go ugly compromises, [like this](https://stackoverflow.com/questions/24963705/is-there-an-escape-character-for-envsubst):\n\n```nginx\n# Example of nginx config template for envsubst.\nserver {\n    listen       $PORT;\n    server_name  localhost;\n    root $NGINX_WEBROOT;\n\n    client_header_timeout $NGINX_CLIENT_HEADER_TIMEOUT;\n    client_body_timeout $NGINX_CLIENT_BODY_TIMEOUT;\n    client_max_body_size $NGINX_MAX_BODY_SIZE;\n\n    location / {\n        try_files ${DOLLAR}uri ${DOLLAR}uri/ @rewrites;\n    }\n\n    location @rewrites {\n        rewrite ^(.+)$ /index.html last;\n    }\n\n    location ~* \\.(?:ico|css|js|gif|jpe?g|png)$ {\n        # Some basic cache-control for static files to be sent to the browser\n        expires max;\n        add_header Pragma public;\n        add_header Cache-Control \"public, must-revalidate, proxy-revalidate\";\n    }\n\n    # redirect server error pages to the static page /50x.html\n    #\n    error_page   500 502 503 504  /50x.html;\n    location = /50x.html {\n        root   $NGINX_WEBROOT;\n    }\n}\n```\n\nDo you see ugly `${DOLLAR}` solution? It's not readable and just terrible. Also `envsubst` if not found any variable in the system scope, he replaces her with an empty string (if replace `${DOLLAR}uri` with `$uri` in this config and was run `envsubst` again, variable `$url` will be replaced to empty string). It is not comfortable.\n\nTo resolve this problem I was created this small template engine.\n\n## Guide\n\nThis is a full guide includes work with docker image.\n\n1. Create a new template file with environment variables which need to be replaced. How example, the same config on the top:\n\n```nginx\nserver {\n    listen       $PORT;\n    server_name  localhost;\n    root $NGINX_WEBROOT;\n\n    client_header_timeout $NGINX_CLIENT_HEADER_TIMEOUT;\n    client_body_timeout $NGINX_CLIENT_BODY_TIMEOUT;\n    client_max_body_size $NGINX_MAX_BODY_SIZE;\n\n    location / {\n        try_files $uri $uri/ @rewrites;\n    }\n\n    location @rewrites {\n        rewrite ^(.+)$ /index.html last;\n    }\n\n    location ~* \\.(?:ico|css|js|gif|jpe?g|png)$ {\n        # Some basic cache-control for static files to be sent to the browser\n        expires max;\n        add_header Pragma public;\n        add_header Cache-Control \"public, must-revalidate, proxy-revalidate\";\n    }\n\n    # redirect server error pages to the static page /50x.html\n    #\n    error_page   500 502 503 504  /50x.html;\n    location = /50x.html {\n        root   $NGINX_WEBROOT;\n    }\n}\n```\n\n[Real example.](https://github.com/roquie/docker-php-webapp/blob/master/conf/nginx/nginx.conf.tmpl)\n\n2. Give the name to him and add `.tmpl` extension (extension not required, but this more readable), for example: `nginx_spa.conf.tmpl`\n\n[Real example.](https://github.com/roquie/docker-php-webapp/blob/master/conf/nginx)\n\n3. Create a new `entry.sh` the script, define default env variables and write command to replace theirs.\n\n```bash\n#!/usr/bin/env sh\n\nexport PORT=${PORT:=8080}\nexport NGINX_WEBROOT=${NGINX_WEBROOT:=\"/srv/www\"}\nexport NGINX_CLIENT_HEADER_TIMEOUT=${NGINX_HEADER_TIMEOUT:=\"120s\"}\nexport NGINX_CLIENT_BODY_TIMEOUT=${NGINX_BODY_TIMEOUT:=\"120s\"}\nexport NGINX_MAX_BODY_SIZE=${NGINX_MAX_BODY_SIZE:=\"2G\"}\n\n# replace variables before start\nsmalte build --scope PORT --scope NGINX\\.* \\\n    /etc/nginx/nginx_spa.conf.tmpl:/etc/nginx/conf.d/default.conf\n\n# run nginx as main container process\nnginx -g \"daemon off;\"\n```\n\nBefore `:` symbol places path to the template file, after – to result of the build.\n`--scope` option reduces the list of global env variables to the selected. Supports regular expressions.\n\n[Real example](https://github.com/roquie/docker-php-webapp/blob/master/conf/start.sh)\n\n4. Copy config template file and `smalte` binary to you Docker-image:\n\n```Dockerfile\nFROM nginx:mainline-alpine\n\nENV NGINX_WEBROOT /usr/share/nginx/html\nENV PORT 8080\n\nCOPY nginx_spa.conf.tmpl /etc/nginx/nginx_spa.conf.tmpl\n# chmod +x ./entry.sh before copy paste to image.\nCOPY entry.sh /\nCOPY --from=roquie/smalte:latest-alpine /app/smalte /usr/local/bin/smalte\n\nWORKDIR /usr/share/nginx/html\n\nCMD [\"/entry.sh\"]\n```\n\n[Real example](https://github.com/roquie/docker-php-webapp/blob/master/Dockerfile#L47)\n\n5. Build docker-image and run. Enjoy.\n\nFiles used in guide located in the example directory.\nMore examples can be found in the tests folder. Also, available Docker-image where using this helper:\nhttps://github.com/roquie/docker-php-webapp\n\n## Example how to overwrite env variable at run\n\nJust pass defined variables to `-e` options of docker run command, like this:\n\n```bash\ndocker run -it --rm -e PORT=3000 -p 9090:3000 roquie/docker-php-webapp:latest\n```\n\nBy default, this container uses 8080 port for nginx. At startup, I replaced the port with a different value (`3000`) uses the `$PORT` environment variable.\n\nTest it:\n```bash\n$ curl http://localhost:9090\n$ Hello world\n```\n\n## Depends\n\n* libpcre\n\n## Docker\n\nAvailable Docker images for Ubuntu 18.04 and Alpine 3.8\n\n## CLI Help\n\n```bash\n\u003e Smalte - is a dead simple and lightweight template engine.\n\n  Example:\n    ./smalte build --scope NGINX\\.* --scope NPM \\\n                test.conf.tmpl:test.conf \\\n                test.conf.tmpl:test2.conf \\\n                test.conf.tmpl:testN.conf\n\n  Usage:\n    smalte build [--scope=\u003cscope\u003e ...] \u003cinputfile:outputfile\u003e...\n    smalte (-h | --help)\n    smalte (-v | --version)\n\n  Options:\n\n    -h --help      Show this screen.\n    -v --version   Show version.\n```\n\n## Usage from a Docker container\n\n```Dockerfile\nFROM ubuntu:18.04\nCOPY --from=roquie/smalte:latest /app/smalte /usr/local/bin/smalte\n\nCMD [\"/usr/local/bin/smalte\"]\n```\n\n## The MIT License (MIT)\n\nCopyright (c)\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Froquie%2Fsmalte","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Froquie%2Fsmalte","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Froquie%2Fsmalte/lists"}