Mix.install cannot be used inside a Mix project?

I am trying to install extra libraries into a running instance of elixir app. The app runs inside k8s container. I remote shell to the instance with kubectl exec -it then at the prompt:

bash# iex --name ddd@ --cookie cookie --remsh app@

and the I do this:

iex(app@> Mix.install([:recon])
** (Mix.Error) Mix.install/2 cannot be used inside a Mix project
    (mix 1.14.0) lib/mix.ex:513: Mix.raise/2
    (mix 1.14.0) lib/mix.ex:656: Mix.install/2
    iex:1: (file)

I do not understand what this means? Can anyone explain what it means? Why mix project is special? And if there is another way to install a dependency?

Mix.install was added in order to improve work with single file scripts which obviously cannot define separate mix.exs file. It uses internal API to … let’s say simulate a project by pushing some data (like dependencies) and executes the script after those are fetched and compiled … in the temporary directory.

Anyway it’s not easy if you want to install dependencies after deployment. Firstly you do not have app like in dev environment, but a release(d app) in prod. Those are much different and simply adding more deps source code would not work or would cause another problems. You would need not only to send a released dependencies, but also update the app itself. Also the directory structure is not guaranteed to be the same across all environments, so even if you would use mix deps.get or any other dev tool the app may not even see new files. Not even saying that mix is not always available on prod machine. There are many other "but"s …

This function can only be called outside of a Mix project and only with the same dependencies in the given VM.

Note: this feature is currently experimental and it may change in future releases.

Source: Mix — Mix v1.14.4

It’s much more easier to release the application again with a new dependencies. I honestly do not see why you want to do this from command line.

1 Like

Not sure I understand all the complexities here. This is what I did to get recon going:

  1. download recon package.
  2. untar/ungzip it
  3. attach to my shell and call Code.append_path/1 with ebin directory of expanded package. This allowed me to run recon on the running instance without re-deploy.

The reason re-deploys in this case are not a good idea is because you have a misbehaving instance already and you want to explore possible problems on that instance you rarely want to restart it.

Maybe it is worth adding another method to Mix.append_package/1 without doing all that extra checking. Code.append_path/1 does not take mix spec it would be totally handy if it did. Anyway just an idea.

1 Like

You can build the dependency by itself with mix archive.build and then upload the .ez file to your server and add that to the code path. That way you can choose the exact version you upload. Of course it’s much more work than just calling mix install but you can script it.

Same for @ashneyderman, but in @lud’s reply the problem is more clear. What if some hex archive/package would have a dependency conflict with said project? This is one of many checks mix do in dev environment before fetching dependencies. Secondly those are really non-standard ways and they are extremely unclear. Even if there would be a nice way to do so in prod how the rest devops team would know it’s available since they are not a part of mix.exs anyway. :confused:

Great! Simple man in the middle attack allows the attacker to have user permissions on prod machine with a possibility of fetching more code. This is the difference between dev where any compilable solution works and prod server which needs to be secured. Not looked at mix source, but I guess there at least should be some checksum checks. :key:

Especially if you have a prod server you don’t want to restart too often you should not mess up with the project and its dependencies. Just in case did you ever considered that something may go wrong
when doing so? I discovered it on one project which is now not maintained, but it’s still a good example and especially when it’s unmaintained.

This directory contains a copy of djm/table_rex.

A hard copy is used instead of a dependency so that mix archive.install ..., which does not recognize the archive’s defined dependencies, is supported.

If you want to use table_rex on yourself then you would notice lots of warnings about overwritten module. Obviously you could have a problem with updating table_rex since a hard copy is obviously not maintained as well.

If some bug appears only in prod then all you need to do is to run a copy of it on a VirtualBox. Same goes for database, if there are problems with it you can just create a dump. If you have some extremely edge cases then anyway delivering a special feature for them is not something a core team would likely do.