{"id":18603627,"url":"https://github.com/cogini/mix-deploy-example","last_synced_at":"2025-06-25T19:02:51.607Z","repository":{"id":35738759,"uuid":"183219147","full_name":"cogini/mix-deploy-example","owner":"cogini","description":"Example Elixir app which uses mix_systemd and mix_deploy to deploy","archived":false,"fork":false,"pushed_at":"2023-10-06T03:50:29.000Z","size":906,"stargazers_count":42,"open_issues_count":24,"forks_count":9,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-06-13T16:09:09.745Z","etag":null,"topics":["elixir-application","elixir-lang"],"latest_commit_sha":null,"homepage":"","language":"HTML","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cogini.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":"2019-04-24T11:55:17.000Z","updated_at":"2024-11-26T10:13:10.000Z","dependencies_parsed_at":"2024-12-27T01:02:27.427Z","dependency_job_id":null,"html_url":"https://github.com/cogini/mix-deploy-example","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/cogini/mix-deploy-example","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cogini%2Fmix-deploy-example","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cogini%2Fmix-deploy-example/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cogini%2Fmix-deploy-example/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cogini%2Fmix-deploy-example/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cogini","download_url":"https://codeload.github.com/cogini/mix-deploy-example/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cogini%2Fmix-deploy-example/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":261937021,"owners_count":23232843,"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":["elixir-application","elixir-lang"],"created_at":"2024-11-07T02:14:57.677Z","updated_at":"2025-06-25T19:02:51.584Z","avatar_url":"https://github.com/cogini.png","language":"HTML","readme":"# mix_deploy_example\n\nThis is a working example Elixir app which shows how to deploy using\n[mix_deploy](https://github.com/cogini/mix_deploy) to a local system and via\n[AWS CodeDeploy](https://aws.amazon.com/codedeploy/).\n\n`mix_deploy` generates scripts which are used to deploy your app using systemd\non a server. It includes scripts to set up the initial system, deploy\ncode and handle configuration during startup. It uses\n[mix_systemd](https://github.com/cogini/mix_systemd) to generate systemd unit\nfiles.\n\n# Deploying locally\n\nThese instructions show how to deploy an app to the same server you are building\non. That can be a $5/month [Digital Ocean](https://m.do.co/c/150575a88316) server.\n\n## Install build dependencies\n\nInstall Erlang, Elixir and Node.js from OS packages:\n\n```shell\n# Ubuntu\nLANG=en_US.UTF-8 sudo bin/build-install-deps-ubuntu\n\n# CentOS\nLANG=en_US.UTF-8 sudo bin/build-install-deps-centos\n```\n\nor install using [ASDF](https://www.cogini.com/blog/using-asdf-with-elixir-and-phoenix/):\n\n```shell\n# Ubuntu\nLANG=en_US.UTF-8 sudo bin/build-install-asdf-deps-ubuntu \u0026\u0026 bin/build-install-asdf-init\n\n# CentOS\nLANG=en_US.UTF-8 sudo bin/build-install-asdf-deps-centos \u0026\u0026 bin/build-install-asdf-init\n```\n\nWe normally use ASDF, but compiling from source on a small server takes a while\nand may run out of RAM unless you adjust the config.\n\n## Configure\n\nThis example loads environment vars from `/srv/mix-deploy-example/etc/environment`:\n\n```elixir\nconfig :mix_systemd,\n  # Run scripts before starting the app\n  exec_start_pre: [\n    # Run db migrations script /srv/mix-deploy-example/bin/deploy-migrate\n    [:deploy_dir, \"/bin/deploy-migrate\"],\n  ],\n  dirs: [\n    # Create runtime temp dir /run/mix-deploy-example\n    :runtime,\n  ],\n  env_files: [\n    # Load environment vars from /srv/mix-deploy-example/etc/environment\n    [\"-\", :deploy_dir, \"/etc/environment\"],\n  ],\n  env_vars: [\n    # Tell release scripts to use runtime directory for temp files\n    # Needed by config/releases.exs\n    [\"RELEASE_TMP=\", :runtime_dir],\n  ]\n\nconfig :mix_deploy,\n  # Generate these scripts from templates\n  templates: [\n    # systemctl wrappers\n    \"start\",\n    \"stop\",\n    \"restart\",\n    \"enable\",\n\n    # System setup\n    \"create-users\",\n    \"create-dirs\",\n    \"set-perms\",\n\n    # Local deploy\n    \"init-local\",\n    \"copy-files\",\n    \"release\",\n    \"rollback\",\n\n    # Release commands\n    \"set-env\",\n    \"remote-console\",\n    \"migrate\",\n  ],\n  # Match mix_systemd\n  env_files: [\n    [\"-\", :deploy_dir, \"/etc/environment\"],\n  ],\n  env_vars: [\n    # Tell release scripts to use runtime directory for temp files\n    [\"RELEASE_TMP=\", :runtime_dir],\n  ],\n  dirs: [\n    :runtime,\n  ],\n  # Copy config/environment from project to /etc/mix-deploy-example/etc/environment\n  copy_files: [\n    %{\n      src: \"config/environment\",\n      dst: [:deploy_dir, \"/etc/environment\"],\n      user: \"$DEPLOY_USER\",\n      group: \"$APP_GROUP\",\n      mode: \"640\"\n    },\n  ]\n```\n\nSet up your production db password and `secret_key_base`, used by Phoenix to protect\nsession cookies.\n\nGenerate `secret_key_base`:\n\n```shell\nmix phx.gen.secret 64\n```\n\nCreate a database using\n[Digital Ocean's Managed Databases Service](https://www.cogini.com/blog/multiple-databases-with-digital-ocean-managed-databases-service/)\nand get the database connection URL.\n\nCreate the file `config/environment` with app secrets:\n\n```shell\nSECRET_KEY_BASE=\"EOdJB1T39E5Cdeebyc8naNrOO4HBoyfdzkDy2I8Cxiq4mLvIQ/0tK12AK1ahrV4y\"\nDATABASE_URL=\"ecto://doadmin:SECRET@db-postgresql-sfo2-xxxxx-do-user-yyyyyy-0.db.ondigitalocean.com:25060/defaultdb?ssl=true\"\n```\n\nAdd `config/environment` to `.gitignore`.\n\n`bin/deploy-copy-files` copies `config/environment` to `/srv/mix-deploy-example/environment/etc`.\n`systemd` then loads it on startup, setting OS environment vars.\n\nConfigure `config/releases.exs` to use `System.get_env/2` to read config from\nthe environment vars:\n\n```elixir\nconfig :mix_deploy_example, MixDeployExampleWeb.Endpoint,\n  http: [:inet6, port: System.get_env(\"PORT\") || 4000],\n  secret_key_base: System.get_env(\"SECRET_KEY_BASE\"),\n  cache_static_manifest: \"priv/static/cache_manifest.json\"\n\nconfig :mix_deploy_example, MixDeployExample.Repo,\n  url: System.get_env(\"DATABASE_URL\")\n```\n\n## Build the system\n\n```shell\nMIX_ENV=prod bin/build\n```\n\nIn addition to the normal build stuff, that does the following:\n\n```\nmix systemd.init\nMIX_ENV=prod mix systemd.generate\n\nmix deploy.init\nMIX_ENV=prod mix deploy.generate\nchmod +x bin/*\n```\n\nInitialize the libraries, copying templates from `mix_systemd` and `mix_deploy`\npackage dirs to `rel/templates`, then generate files based on the config in\n`config/prod.exs`:\n\n## Initialize the local system\n\nSet up the local system for the app, creating users, directories, etc:\n\nsudo bin/deploy-init-local\n\nTHat does the following:\n\n```shell\nbin/deploy-create-users\nbin/deploy-create-dirs\n\ncp bin/* /srv/mix-deploy-example/bin\n\nbin/deploy-copy-files\nbin/deploy-enable\n```\n\n# Log out and log in again\n\nThe `bin/deploy-create-users` adds the deploy user to the group used by the\napp. In order for that to take effect, you have to log out and log in again.\n\n## Build\n\nBuild the app and make a release:\n\n```shell\nMIX_ENV=prod bin/build\n```\n\n## Deploy\n\nDeploy the release to the local machine:\n\n```shell\n# Extract release to target directory, creating current symlink\nbin/deploy-release\n\n# Restart the systemd unit\nsudo bin/deploy-restart\n```\n\nCheck the status:\n```shell\nsystemctl status mix-deploy-example\njournalctl -f -u mix-deploy-example\n```\n\n## Test\n\nTest it by making a request to the server:\n\n```shell\ncurl -v http://localhost:4000/\n```\n\nIf things aren't working right, you can roll back to the previous release:\n\n```shell\nbin/deploy-rollback\nsudo bin/deploy-restart\n```\n\n# Preparing an existing project for deployment\n\nFollowing are the steps used to set up this repo. You can do the same to add\nit to your own project.\n\n## Generate Phoenix project\n\n```shell\nmix phx.new mix_deploy_example\nmix deps.get\ncd assets \u0026\u0026 npm install \u0026\u0026 node node_modules/webpack/bin/webpack.js --mode development\n```\n\n- Add `mix.lock` to git\n- Add `package-lock.json` to git\n\n## Configure Elixir 1.9+ mix releases\n\nConfigure releases in `mix.exs`:\n\n```elixir\ndefp releases do\n  [\n    prod: [\n      include_executables_for: [:unix],\n      steps: [:assemble, :tar]\n    ],\n  ]\nend\n```\n\nConfigure `rel/env.sh.eex` and `rel/vm.args.eex` if necessary, e.g.\nto [increase network ports](https://www.cogini.com/blog/tuning-tcp-ports-for-your-phoenix-app/).\n\nSee [the docs](https://hexdocs.pm/mix/Mix.Tasks.Release.html) for more details.\n\n## Install mix_deploy and mix_systemd\n\nAdd libraries to deps from Hex:\n\n```elixir\n{:mix_deploy, \"~\u003e 0.7\"}\n```\n\nAdd `rel/templates` and `bin/deploy-*` to `.gitignore`.\n\n## Copy build and utility scripts\n\nCopy scripts from the `bin/` directory to the `bin/` directory of your project.\n\nThese scripts install the required dependencies:\n\n- `build-install-asdf`\n- `build-install-asdf-deps-centos`\n- `build-install-asdf-deps-ubuntu`\n- `build-install-asdf-init`\n- `build-install-asdf-macos`\n- `build-install-deps-centos`\n- `build-install-deps-ubuntu`\n\nThis script builds the app:\n\n- `build`\n\nThis script verifies that the app is running correctly:\n\n- `bin/validate-service`\n\n## Configure Phoenix for OTP releases\n\nUpdate `config/prod.exs` to run from release:\n\n- Start Phoenix endpoints automatically\n\n```elixir\nconfig :phoenix, :serve_endpoints, true\n```\n\n- Don't import `prod.secret.exs`\n\n```elixir\n`# import_config \"prod.secret.exs\"`\n```\n\n## Configure mix_deploy and mix_systemd\n\nConfigure `mix_deploy` and `mix_systemd` in `config/prod.exs`.\n\n## Configure ASDF\n\nCreate a `.tool-versions` file in the root of your project, describing the versions\nof OTP, Elixir, and Node that you will be building with:\n\n```\nerlang 22.2\nelixir 1.9.4\nnodejs 10.15.3\n```\n\n## Configure for CodeDeploy\n\n- Add `appspec.yml`\n\n## Configure for CodeBuild\n\n- Add `buildspec.yml`\n\n## Add database migrations\n\n- Add `lib/mix_deploy_example/release.ex` as described in\n  [Ecto migrations and custom commands](https://hexdocs.pm/phoenix/releases.html#ecto-migrations-and-custom-commands)\n\n## Add TOML config provider\n\n- Add to `mix.exs`\n\n```elixir\ndefp deps do\n  [\n    {:toml_config, \"~\u003e 0.1.0\"}, # Mix releases\n  ]\nend\n```\n\n```\ndefp releases do\n  [\n    aws: [\n      include_executables_for: [:unix],\n      config_providers: [\n        {TomlConfigProvider, path: \"/etc/mix-deploy-example/config.toml\"}\n      ],\n      steps: [:assemble, :tar]\n    ],\n  ]\nend\n```\n\n## Add Ansible scripts\n\nSee `ansible` dir.\n\n## Add Docker file\n\n```shell\nbuild -f build/docker/Dockerfile .\n```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcogini%2Fmix-deploy-example","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcogini%2Fmix-deploy-example","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcogini%2Fmix-deploy-example/lists"}