{"id":16584338,"url":"https://github.com/markdumay/countly-secret","last_synced_at":"2026-05-16T00:38:46.301Z","repository":{"id":119865502,"uuid":"264610372","full_name":"markdumay/countly-secret","owner":"markdumay","description":"Deploy Countly Analytics as Docker Stack with Secure Credentials (work in progress)","archived":false,"fork":false,"pushed_at":"2020-06-20T06:30:44.000Z","size":248,"stargazers_count":1,"open_issues_count":1,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-10-28T15:56:04.981Z","etag":null,"topics":["countly","docker","docker-swarm-secret"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","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/markdumay.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-05-17T07:49:18.000Z","updated_at":"2021-02-19T14:56:23.000Z","dependencies_parsed_at":"2023-06-03T11:00:27.462Z","dependency_job_id":null,"html_url":"https://github.com/markdumay/countly-secret","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/markdumay/countly-secret","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/markdumay%2Fcountly-secret","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/markdumay%2Fcountly-secret/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/markdumay%2Fcountly-secret/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/markdumay%2Fcountly-secret/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/markdumay","download_url":"https://codeload.github.com/markdumay/countly-secret/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/markdumay%2Fcountly-secret/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":281467276,"owners_count":26506462,"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","status":"online","status_checked_at":"2025-10-28T02:00:06.022Z","response_time":60,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["countly","docker","docker-swarm-secret"],"created_at":"2024-10-11T22:44:26.579Z","updated_at":"2025-10-28T15:56:08.338Z","avatar_url":"https://github.com/markdumay.png","language":"JavaScript","funding_links":["https://www.buymeacoffee.com/markdumay"],"categories":[],"sub_categories":[],"readme":"# countly-secret (work in progress)\n\n\u003c!-- Tagline --\u003e\n\u003cp align=\"center\"\u003e\n    \u003cb\u003eDeploy Countly Analytics as Docker Stack with Secure Credentials\u003c/b\u003e\n    \u003cbr /\u003e\n\u003c/p\u003e\n\n\n\u003c!-- Badges --\u003e\n\u003cp align=\"center\"\u003e\n    \u003ca href=\"https://github.com/markdumay/countly-secret/commits/master\" alt=\"Last commit\"\u003e\n        \u003cimg src=\"https://img.shields.io/github/last-commit/markdumay/countly-secret.svg\" /\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://github.com/markdumay/countly-secret/issues\" alt=\"Issues\"\u003e\n        \u003cimg src=\"https://img.shields.io/github/issues/markdumay/countly-secret.svg\" /\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://github.com/markdumay/countly-secret/pulls\" alt=\"Pulls\"\u003e\n        \u003cimg src=\"https://img.shields.io/github/issues-pr-raw/markdumay/countly-secret.svg\" /\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://github.com/markdumay/countly-secret/blob/master/LICENSE\" alt=\"License\"\u003e\n        \u003cimg src=\"https://img.shields.io/github/license/markdumay/countly-secret.svg\" /\u003e\n    \u003c/a\u003e\n\u003c/p\u003e\n\n\u003c!-- Table of Contents --\u003e\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"#about\"\u003eAbout\u003c/a\u003e •\n  \u003ca href=\"#built-with\"\u003eBuilt With\u003c/a\u003e •\n  \u003ca href=\"#prerequisites\"\u003ePrerequisites\u003c/a\u003e •\n  \u003ca href=\"#testing\"\u003eTesting\u003c/a\u003e •\n  \u003ca href=\"#deployment\"\u003eDeployment\u003c/a\u003e •\n  \u003ca href=\"#usage\"\u003eUsage\u003c/a\u003e •\n  \u003ca href=\"#donate\"\u003eDonate\u003c/a\u003e •\n  \u003ca href=\"#license\"\u003eLicense\u003c/a\u003e\n\u003c/p\u003e\n\n\n## About\n[Countly][countly_info] is an open-source analytics platform to track customer journeys in web, desktop, and mobile applications. The community edition has a free-to-use non-commercial license and can be self-hosted. Countly consists of an API and a portal, using a Mongo database for data persistency. Countly Secret is a configuration script to deploy Countly, a Mongo database, and a reverse proxy as Docker containers. It uses Docker Swarm secrets to secure the database credentials. \n\n\u003c!-- TODO: add tutorial deep-link \nDetailed background information is available on the author's [personal blog][blog].\n--\u003e\n\n## Built With\nThe project uses the following core software components:\n* [Countly][countly_url] - Analytics platform\n* [Docker][docker_url] - Container platform (including Swarm and Compose)\n* [MongoDB][mongodb_url] - Document-based distributed database\n* [HTTPS Portal][portal_url] - Fully automated HTTPS server\n\n\n## Prerequisites\nCountly Secret can run on a local machine for testing purposes or in a production environment. The setup has been tested locally on macOS and a Virtual Private Server (VPS) running Ubuntu 18.04 LTS.\n\n### Recommended Server Sizing\nIn a minimal setup, Countly and its accompanying Mongo database can be deployed on the same server. For a website with moderate traffic, 2 CPU cores, 4 GB of RAM and 100 GB disk space should be sufficient to get you started. This [overview][countly_deployment] shows the setup for requirements and deployment options for increased workload levels.\n\n### Host Operating System\nAs Countly will be deployed as a Docker container, in theory any host operating system will do, as long as it supports Docker. However, for a production system, a Long Term Support (LTS) version of a major Linux distribution such as Ubuntu or CentOS is recommended. \n\n### Other Prerequisites\n* \u003cb\u003eA registered domain name is required\u003c/b\u003e - \nNot only will this help you access the Countly dashboard and API, but it is also required for configuring SSL certificates to enable secure web traffic. You should have the ability to manually configure DNS entries for your domain too.\n\n* \u003cb\u003eDocker Compose and Docker Swarm are required\u003c/b\u003e - Countly and the Mongo Database will be deployed as Docker containers in swarm mode to enable Docker *secrets*.\n\n* \u003cb\u003eAn email service is optional\u003c/b\u003e - Having an email service allows you to receive system notifications from Countly.\n\u003c!-- TODO: email configuration --\u003e\n\n## Testing\nIt is recommended to test the services locally before deploying them to production. Running the services with `docker-compose` greatly simplifies the validation of the service logs. Below four steps will allow you to run the services on your local machine.\n\n### Step 1 - Clone the Repository\nThe first step is to clone the repository to a local folder. Assuming you are in the working folder of your choice, clone the repository files. Git automatically creates a new folder `countly-secret` and copies the files to this directory. The option `--recurse-submodules` ensures the embedded submodules are fetched too. Now change your working folder to be prepared for the next steps.\n\n```console\ngit clone --recurse-submodules https://github.com/markdumay/countly-secret.git\ncd countly-secret\n```\n\n### Step 2 - Create Docker Secret Files\nAs Docker-compose does not support external Swarm secrets, we will create local secret files for testing purposes. The credentials are stored as plain text, so this is not recommended for production.\n\n```console\nmkdir secrets\nprintf admin \u003e secrets/mongodb_root_username.txt\nprintf password \u003e secrets/mongodb_root_password.txt\nprintf countly \u003e secrets/countly_mongodb_username.txt\nprintf password \u003e secrets/countly_mongodb_password.txt\n```\n\n### Step 3 - Update the Environment Variables\nThe `docker-compose.yml` file uses environment variables to simplify the configuration. You can use the sample file in the repository as a starting point.\n\n```console\nmv sample.env .env\n```\n\nThe `.env` file specifies four variables. Adjust them as needed.\n```\nMONGODB_DATABASE=countly\nDOMAINS_COUNTLY=countly.example.test\nCOUNTLY_API_HOST=http://api:3001\nCOUNTLY_FRONTEND_HOST=http://frontend:6001\n```\n\nIt's convenient to use a `.test` top-level domain for testing. This domain is reserved for this purpose and is guaranteed not to clash with an existing domain name. However, you will still need to resolve these domains on your local machine. Steven Rombauts wrote an excellent [tutorial][macos_dnsmasq] on how to configure this using `dnsmasq` on macOS.\n\n### Step 4 - Run with Docker Compose\nTest the Docker services with `docker-compose`. You can stop the services with the command `ctrl-c`.\n\n```console\ndocker-compose up\n```\n\n### Step 5 - Validate the Service Logs\nThe initialization of the services typically takes a few minutes. Below key messages show the status of the individual services and indicate when they are ready.\n\n```\nmongodb_1   | I  CONTROL  [initandlisten] options: { net: { bindIp: \"*\" }, security: { authorization: \"enabled\" } }\nmongodb_1   | I  NETWORK  [listener] Listening on 0.0.0.0\nfrontend_1  | Done.\nfrontend_1  | removed ** packages and audited ** packages in **s\napi_1       | Done.\napi_1       | removed ** packages and audited ** packages in **s\nportal_1    | Self-signing test certificate for countly.example.test\nportal_1    | [services.d] done.\n```\n\n## Deployment\nThe steps for deploying in production are slightly different than for local testing. Below six steps guide you through the setup.\n\n### Step 1 - Clone the Repository\nThe first step is to clone the repository to a local folder. Assuming you are in the working folder of your choice, create a new directory `countly-secret` (or any folder name of your liking) and clone the repository files. The final `.` instructs git to put the files in the current directory.\n\n```console\nmkdir countly-secret\ncd countly-secret\ngit clone https://github.com/markdumay/countly-secret.git .\n```\n\n\n### Step 2 - Create Docker Swarm Secrets\nDocker secrets can be easily created using pipes. The passwords are randomized using `openssl`, but feel free to use another method to your liking. Do not forget the include the final `-`, as this instructs Docker to use piped input. \n\n```console\nprintf admin | docker secret create mongodb_root_username -\nopenssl rand -base64 32 | docker secret create mongodb_root_password -\nprintf countly | docker secret create countly_mongodb_username -\nopenssl rand -base64 32 | docker secret create countly_mongodb_password -\n```\n\nIf you do not feel comfortable copying secrets from your command line, you can use the wrapper `create_secret.sh`. This script prompts for a secret and ensures sensitive data is not displayed in your console. The script is available in the folder `/docker-secret` of your repository.\n\n```console\n./create_secret.sh mongodb_root_username\n./create_secret.sh mongodb_root_password\n./create_secret.sh countly_mongodb_username\n./create_secret.sh countly_mongodb_password\n```\n\n### Step 3 - Update the Docker Compose File\nThe `docker-compose.yml` in the repository defaults to set up for local testing. Update the `secrets` section to use Docker Swarm secrets instead of local files.\n\n```Dockerfile\nsecrets:\n    mongodb_root_username:\n        external: true\n    mongodb_root_password:\n        external: true\n    countly_mongodb_username:\n        external: true\n    countly_mongodb_password:\n        external: true\n```\n\nIn the same file, instruct HTTPS Portal to request certificates from Let's Encrypt by setting the `STAGE` environment variable to `production`.\n```Dockerfile\nservices:\n    portal:\n        environment:\n            STAGE: production\n```\n\n### Step 4 - Update the Environment Variables\nThe `docker-compose.yml` file uses environment variables to simplify the configuration. You can use the sample file in the repository as a starting point.\n\n```console\nmv sample.env .env\n```\n\nThe `.env` file specifies four variables. Adjust them as needed. Docker creates an alias for the hostnames, so you should not have to rename `api` to `countly_api` or `frontend` to `countly_frontend`.\n```\nMONGODB_DATABASE=countly\nDOMAINS_COUNTLY=countly.example.com\nCOUNTLY_API_HOST=http://api:3001\nCOUNTLY_FRONTEND_HOST=http://frontend:6001\n```\n\n\n### Step 5 - Run with Docker Stack\nUnlike Docker Compose, Docker Stack does not automatically create local folders. Create an empty folder for the Mongo database and the HTTPS portal. Next, deploy the Docker Stack using `docker-compose` as input. This ensures the environment variables are parsed correctly.\n\n```console\nmkdir data\nmkdir data/mongodb\nmkdir data/portal\ndocker-compose config | docker stack deploy -c - countly\n```\n\n### Step 6 - Inspect the Status of the Stack\nRun the following command to inspect the status of the Docker Stack.\n\n```console\ndocker stack services countly\n```\n\nYou should see the value `1/1` for `REPLICAS` for each service if the stack was initialized correctly. It might take a while before the services are up and running, so simply repeat the command after a few minutes if needed.\n\n```\nID  NAME                MODE        REPLICAS    IMAGE                               PORTS\n*** countly_frontend    global      1/1         markdumay/countly-frontend:20.04\n*** countly_portal      replicated  1/1         steveltn/https-portal:1             *:80-\u003e80/tcp, *:443-\u003e443/tcp\n*** countly_api         replicated  1/1         markdumay/countly-api:20.04\n*** countly_mongodb     replicated  1/1         mongo:4.2\n```\n\nDebugging swarm services can be quite challenging. If for some reason your service does not initiate properly, you can get its task ID with `docker service ps \u003cservice-name\u003e`. Running `docker inspect \u003ctask-id\u003e` might give you some clues to what is happening. If the service did initiate correctly, you can view the service log with `docker service logs \u003cservice-name\u003e`. Use `docker stack rm countly` to remove the docker stack entirely. Be aware not to redeploy the stack before all services and networks have been completely removed, as this might result in [errors][issue_30942].\n\n\n## Usage\nOpen your internet browser and navigate to the URL specified in your `.env` file. The default value is `countly.example.test` or `countly.example.com` pending you are in test mode or production. The site's certificate is self-signed in a local setup, so you might need to instruct your internet browser to trust this certificate. The site should now display the welcome screen of Countly and will ask you to set up an administrative user. \n\n![Countly setup screen][image_setup]\n\nIf you do not see the full dashboard, try to log in again. Countly is now ready for use.\n\n![Countly home screen][image_home]\n\n\n## Contributing\n1. Clone the repository and create a new branch \n    ```\n    $ git checkout https://github.com/markdumay/countly-secret.git -b name_for_new_branch\n    ```\n2. Make and test the changes\n3. Submit a Pull Request with a comprehensive description of the changes\n\n## Donate\n\u003ca href=\"https://www.buymeacoffee.com/markdumay\" target=\"_blank\"\u003e\u003cimg src=\"https://cdn.buymeacoffee.com/buttons/lato-orange.png\" alt=\"Buy Me A Coffee\" style=\"height: 51px !important;width: 217px !important;\"\u003e\u003c/a\u003e\n\n## License\n\u003ca href=\"https://github.com/markdumay/countly-secret/blob/master/LICENSE\" alt=\"License\"\u003e\n    \u003cimg src=\"https://img.shields.io/github/license/markdumay/countly-secret.svg\" /\u003e\n\u003c/a\u003e\n\nCopyright © [Mark Dumay][blog]\n\n\n\n\u003c!-- MARKDOWN LINKS --\u003e\n[countly_deployment]: https://support.count.ly/hc/en-us/articles/360037814151-Deployment-scenarios\n[countly_info]: https://count.ly/product\n[countly_url]: https://count.ly\n[docker_url]: https://docker.com\n[issue_30942]: https://github.com/moby/moby/issues/30942\n[macos_dnsmasq]: https://www.stevenrombauts.be/2018/01/use-dnsmasq-instead-of-etc-hosts/\n[mongodb_url]: https://mongodb.com\n[portal_url]: https://github.com/SteveLTN/https-portal\n\u003c!-- TODO: add blog link\n[blog]: https://markdumay.com\n--\u003e\n[blog]: https://github.com/markdumay\n[repository]: https://github.com/markdumay/countly-secret.git\n\n\u003c!-- MARKDOWN IMAGES --\u003e\n[image_setup]: images/countly-setup.png\n[image_home]: images/countly-home.png\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmarkdumay%2Fcountly-secret","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmarkdumay%2Fcountly-secret","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmarkdumay%2Fcountly-secret/lists"}